首页 练字文章 虚拟机类加载机制

虚拟机类加载机制

2024-09-07 22:04  浏览数:128  来源:redjujubee    

7.2 类加载的时机
一个类型从被加载到虚拟机内存中开始,到卸载为止,它的整个生命周期将会经历
加载(Loading)、验证(Verification)、准备(Preparation)、解析(Resolut
ion)、初始化(Initialization)、使用(Using)、卸载(Unloading)七个阶段,其中
验证、准备、解析这三个阶段统称为连接(Linking)。
有且只有6中情况必须对类立即进行"初始化":
遇到new、getstatic、putstatic、或invokestatic这四条字节码指令时,如果类型没有
经过初始化,则需要先触发其初始化阶段。
使用java.lang.reflect包的方法对类型进行反射调用的时候,如果类型没有进行过初始化,则需要先触发
其初始化。
当初始化类的时候,如果发现其父类还没有进行初始化,则需要先触发其父类的初始化。
当虚拟机启动的时候,用户需要指定一个需要执行的主类(main),虚拟机会先初始化这个主类。
当使用JDK7 新加入的动态语言支持时,如果一个java.lang.invoke.MethodHandle实例
最后的解析结果为
REF_getStatic、REF_putStatic、REF_invokeStatic、REF_newInv
okeSpecial 四种类型的方法句柄,并且这个方法句柄对应的类没有进行初始化,则需要先触发其初始化。
当一个接口定义了JDK8新加入的默认方法(被default关键字修饰的接口方法),如果这个接口的实现类发生了初
始化,那么该接口要在其之前被初始化。
7.3 类加载的过程
7.3.1 加载: 通过一个类的全限定名来获取定义此类的二进制字节流。将这个字节流所代表的静态存储结构转化为方
法区运行时数据结构。在内存中生成一个代表此类的java.lang.Class对象,作为方法区这个类的各种数据的
访问接口。
7.3.2 验证: 确保Class文件中的字节流中包含的信息符合《Java虚拟机规范》的要求,保证这些信息在运
行后不会危害虚拟机自身的安全。
7.3.3 准备:为类的静态变量分配内存并设置类变量的初始值。这些变量所使用的内存都应在方法区中分配,但必须注
意到方法区是一个逻辑上的概念,在JDK1.7 中HotSpot使用永久代来实现方法区是完全符合这一逻辑概念的;
在JDK1.8 之后类变量则会随着Class对象一起分配在Java堆中,这时"类变量在方法区",就完全是一种对
逻辑概念的表述了。
7.3.4 解析:解析阶段是Java虚拟机将常量池内的符号引用替换为直接引用的过程。
7.3.5 初始化:进行准备阶段时,变量已经赋过一次系统要求的初始零值,而在初始化阶段,则会根据程序员通过程序
编码定制的主观计划去初始化类变量和其他资源(调用类的初始化方法)。
7.4 类加载器
7.4.1 双亲委派模型
启动类加载器(Bootstrap Class Loader)
扩展类加载器(Extension Class Loader)
应用程序类加载器(Application Class Loader)
如果一个类加载器收到了加载类的请求,他首先不会自己去尝试加载这个类,而是委派给父类的类加载器完成,每一个层次的
类加载器都是如此,因此所有的类加载请求最终都应该传送到最顶层的启动类加载器中,只有当父加载器反馈自己无法完成这
个加载请求,子加载器才会去尝试自己去完成加载。
7.4.1 破坏双亲委派模型
1) 双亲委派模型出现之前,类加载器和抽象类java.lang.ClassLoader就已经存在,为了兼容这些
代码,无法再以技术手段避免loadClass()被子类覆盖的可能性,只能在
JDK1.2 之后 添加一个新的 protected 方法 findClass() 引导开发人员去尽量去重写这
个方法而不是在loadClass中编写代码。
2) SPI
JNDI服务,它的代码由启动类加载器来加载完成,但是它需要调用由其他厂商实现并部署在应用程序的ClassPat
h 下的JNDI服务提供者(Service Provider Interface)的代码,启动类加载器是绝对不
可能认识、加载这些代码的,为了解决这个困境,Java涉及团队只好引入了线程长下文类加载器(Thread Con
text ClassLoader)。这个类加载器可以通过java.lang.Thread类的setContex
tClassLoader()方法进行设置,如果创建线程的时候还未设置,它将会从父线程中集成一个,如果在应用程序
的全局范围内都没有设置过的话,这个类加载默认就是应用程序类加载器。
在JDK6 时,JDK提供了java.util.ServiceLoader类。以META-INF/servic
es中的配额制信息,辅以责任链模式,这才算给SPI一种相对合理的解决方案。
3) 由于用户对程序动态性能的追求导致的,通常指的是代码热替换(Hot Swap)、模块热部署(Hot Dep
loyment)等
7.5 Java模块化系统
模块下的类加载器(JDK 9)
扩展类加载器(Extension Class Loader)被平台类加载器(Platform Class Lo
ader)替代。
平台类加载器和应用程序类加载器都不在派生自java.netURLClassLoader, 现在启动类加载器,平
台类加载器、应用程序类加载器全部继承自 jdk.internal.loader.BuiltinClassLoa
der



声明:以上文章均为用户自行添加,仅供打字交流使用,不代表本站观点,本站不承担任何法律责任,特此声明!如果有侵犯到您的权利,请及时联系我们删除。

字符:    改为:
去打字就可以设置个性皮肤啦!(O ^ ~ ^ O)