Java 类加载器

目录

类加载过程

类加载器ClassLoader

JVM四级类加载器(向上委托,向下加载,下可用上,上不可用下)

JVM四级类加载器的动态性

类加载器双亲委托

Java严格执行双亲委托机制

双亲委托的补充

自定义加载路径

自定义类加载器


类加载过程

  1. –加载(loading)
  2. –链接(linking)
  •    •验证(Verification),字节码是否满足规范要求
  •    •准备(Preparation),分配内存,常量池初始化
  •    •解析(Resolution),解析类/接口/字段/方法的符号引用

    3.–初始化(Initializing),执行类的初始化方法<clinit>

–类加载器是JVM生态体系的基础构成之一

–程序是依靠多个Java类共同协作完成的

–JVM依据classpath执行的类库的顺序来查找类

–潜在的问题

  •  如何找到正确的类,如classpath路径的前后
  • 如何避免恶意的类,如一个假的String类
  • 加载的顺序,如先加载

类加载器ClassLoader

负责查找、加载、校验字节码的应用程序

–java.lang.ClassLoader

  • •load(String className) 根据名字加载一个类,返回类的实例
  • •defineClass(String name, byte[] b, int off, int len) 将一个字节流定义一个类
  • •findClass(String name) 查找一个类
  • •findLoadedClass(String name) 在已加载的类中,查找一个类
  • •成员变量ClassLoaderparent;

JVM四级类加载器(向上委托,向下加载,下可用上,上不可用下)

JVM四级类加载器严格遵循从上到下的加载机制

–启动类加载器(Bootstrap),系统类rt.jar(静态)

–扩展类加载器(Platform/Extension),jre/lib/ext(静态)

–应用类加载器(App),classpath(静态)

–用户自定义加载器(Plugin),程序自定义(动态)

•优点

–层次分明,逐级加载,确保核心类可信

–兼顾静态和动态

JVM四级类加载器的动态性

–使用虚拟机参数-Xbootclasspath,将jar或目录提高到Bootstrap等级

–使用ServiceLoaderSPI机制,实现上层加载器的类,访问下层加载器的类

–使用URLClassLoader,可以在运行时增加新的classpath路径

–使用自定义的ClassLoader,可以通过重写loadClass和findClass方法动态加载字节码,还可以在加载字节码过程中进行修改/校验等操作

类加载器双亲委托

–首先判断是否已经加载

–若无,找父加载器加载

–若再无,由当前加载器加载

Java严格执行双亲委托机制

JVM四级类加载器严格遵循从上到下的加载机制

类会由最顶层的加载器来加载,如没有,才由下级加载器加载

–委托是单向的,确保上层核心的类的正确性

但是上级类加载器所加载的类,无法访问下级类加载器所加载的类

  • •例如,java.lang.String无法访问自定义的一个Test类
  • •Java是一个遵循契约设计的程序语言,核心类库提供接口应用层提供实现
  • •核心类库是BootstrapClassLoader加载
  • •应用层是AppClassLoader加载
  • •典型例子是JDBC和XML Parser等

双亲委托的补充

–执行Java,添加虚拟机参数

-Xbootclasspath/a:path,将类路径配置为Bootstrap等级

  • •使用java –X 查看具体的帮助

–使用ServiceLoader.load方法,来加载(底层加载器所加载的类)

- 利用ServiceLoader机制可以提供上层加载器的类来访问下层加载器的类

–以JDBC加载为例

 

自定义加载路径

–弥补类搜索路径静态的不足

–URLClassLoader, 从多个URL(jar或者目录)中加载类

–继承于ClassLoader

–程序运行时增加新的类加载路径

–可从多个来源中加载类

•目录

•jar包

•网络

–addURL添加路径

–close方法关闭

  • •程序动态增加类加载路径,克服静态路径的缺点
  • •不同程序/线程可以有不同的加载路径,互相隔离
  • •重复加载某一个路径,实现程序热部署

自定义类加载器

–继承ClassLoader类

–重写findClass(String className)方法

–使用时,默认先调用loadClass(className)来查看是否已经加载过,然后委托双亲加载,如果都没有,再通过findClass加载返回

  • •在findClass中,首先读取字节码文件
  • •然后,调用defineClass(className, bytes, off, len) 将类注册到虚拟机中
  • •可以重写loadClass方法来突破双亲加载
  • 同一个类可以被不同层级的加载器加载,且作为2个类对待
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值