当前位置:首页 / 文章测试 / 虚拟机类加载机制

虚拟机类加载机制

开始打字练习

7.2 类加载的时机

一个类型从被加载到虚拟机内存中开始,到卸载为止,它的整个生命周期将会经历

加载(Loading)、验证(Verification)、准备(Preparation)、解析(Resolution)、初始化(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_newInvokeSpecial 四种类型的方法句柄,并且这个方法句柄对应的类没有进行初始化,则需要先触发其初始化。

当一个接口定义了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服务,它的代码由启动类加载器来加载完成,但是它需要调用由其他厂商实现并部署在应用程序的ClassPath 下的JNDI服务提供者(Service Provider Interface)的代码,启动类加载器是绝对不可能认识、加载这些代码的,为了解决这个困境,Java涉及团队只好引入了线程长下文类加载器(Thread Context ClassLoader)。这个类加载器可以通过java.lang.Thread类的setContextClassLoader()方法进行设置,如果创建线程的时候还未设置,它将会从父线程中集成一个,如果在应用程序的全局范围内都没有设置过的话,这个类加载默认就是应用程序类加载器。

在JDK6 时,JDK提供了java.util.ServiceLoader类。以META-INF/services中的配额制信息,辅以责任链模式,这才算给SPI一种相对合理的解决方案。

3) 由于用户对程序动态性能的追求导致的,通常指的是代码热替换(Hot Swap)、模块热部署(Hot Deployment)等

7.5 Java模块化系统

模块下的类加载器(JDK 9)

扩展类加载器(Extension Class Loader)被平台类加载器(Platform Class Loader)替代。

平台类加载器和应用程序类加载器都不在派生自java.netURLClassLoader, 现在启动类加载器,平台类加载器、应用程序类加载器全部继承自 jdk.internal.loader.BuiltinClassLoader

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