1.类加载机制简介:
Java虚拟机(JVM)的类加载机制是Java应用程序性能调优的关键组成部分。类加载机制不仅负责将类从磁盘加载到内存中,还涉及到类的链接、初始化以及内存管理。本文旨在探讨JVM类加载机制的工作原理,以及如何通过调优类加载过程来提升Java应用程序的性能。
2.类加载过程:
在Java应用程序的生命周期中,类加载机制扮演着至关重要的角色。它确保了应用程序的类在需要时被加载,并且在适当的时候被卸载。JVM的类加载过程包括加载、链接、初始化三个主要阶段。了解这些阶段的工作方式对于进行有效的JVM调优至关重要。
2.1加载阶段
在加载阶段,JVM通过类加载器读取.class文件的二进制数据,并将其转换成一个java.lang.Class对象。这个对象代表了该类在JVM中的一个类定义。
(1)获取类的全限定类名,把class文件转为二进制流
(2)将二进制流中类的描述信息存入方法区中。如:创建时间、版本等...
(3)将java.lang.Class 对象存入堆中。
2.2链接阶段
链接阶段包括验证、准备和解析三个子阶段。验证阶段确保加载的类信息符合JVM规范;准备阶段为类的静态变量分配内存并设置默认初始值;解析阶段将类、接口、字段和方法的符号引用转换为直接引用。
(1)验证:验证被加载类的正确性:如文件的格式,元数据等。
(2)准备:在方法区中为静态变量分配空间,并设置初始值。
(3)解析:把类的符号引用转为直接引用。 符号引用:class文件定义的内容 直接引用:JAVA进程中真实的地址
2.3初始化阶段
在初始化阶段,JVM执行类的静态初始化器和静态变量的赋值操作。这个阶段是类加载过程中耗时最长的阶段,因为JVM需要执行类构造器<clinit>()方法。
为类的静态变量设置默认值、执行静态代码块。初始化就是执行类的构造器方法init
()的过程。这个方法不需要定义,是javac编译器自动收集类中所有类变量的赋值动作和静态代码块中的语句合并来的。
注意:若该类具有父类,jvm
会保证父类的init
先执行,然后在执行子类的init
。
3.类加载器:
什么是类加载器?类加载器是Java虚拟机(JVM)的一个核心组件,负责将类(.class文件)加载到JVM中。在Java中,每个类都由特定的类加载器加载,这是实现Java应用程序模块化和封装的一种机制。类加载器不仅加载类,还负责链接(验证、准备、解析)和初始化类。
3.1类加载器的分类
不同的类加载器加载不同的类:
启动类加载器(BootstrapclassLoader): 主要负责加载JAVA中的 一些核心类库,用C++实现,是虚拟机自带的类加载器。负责加载JAVA_HOME/jre/lib目录中的核心类库,如rt.jar、jsse.jar等,不属于java.lang.ClassLoader的子类。
拓展类加载器(Extension classLoader):主要加载 JAVA 中的一些拓展类,用Java语言实现,继承自ClassLoader类。负责加载JAVA_HOME/jre/lib/ext目录或者由系统属性java.ext.dirs指定位置中的类库。可以通过java.endorsed.dirs指定的目录中的类库也会被加载。
应用类加载器(Application ClassLoader): 也称为系统类加载器(System ClassLoader)。
主要用于加载CLASSPATH路径下我们自己写的类,是拓展类加载器的子类。
用户自定义类加载器:可以通过继承ClassLoader类的方式实现。允许开发者自定义类的加载方式,比如从网络、数据库或其他资源加载类。
3.2双亲委派模型
什么是双亲委派模型?双亲委派模型(Parent Delegation Model)是Java类加载机制中的一个核心原则。这个模型规定了类加载器在加载一个类时的委托流程,确保了Java核心库的类型安全,并使得应用程序可以自定义类加载器来扩展类加载的方式。
工作原理: 如果一个类加载器收到了类加载请求,它并不会自己先去加载,而是把这个请求委托给父类的加载器去执行,如果父类加载器还存在其父类加载器,则进一步向上委托,依次递归,请求最终将到达顶层的启动类加载器。如果父类加载器可以完成类加载任务,就成功返回。 倘若父类加载器无法完成此加载任务,子加载器才会尝试自己去加载。
总结:委托——>父类加载递归——>检测是否已加载——>自己加载——>返回结果
3.3面试题:如何打破双亲委派机制?
-
自定义类加载器: 创建一个自定义类加载器,并重写
loadClass(String name, boolean resolve)
方法。在这个方法中,类加载器可以按照自己的逻辑来加载类,而不是委托给父类加载器。 -
使用
findClass
方法: 在自定义类加载器中,重写findClass
方法来实现自己的类查找和加载逻辑。如果findClass
方法返回了一个类的Class
对象,那么双亲委派模型就会被打破。 -
使用
defineClass
方法: 在findClass
方法中,使用defineClass
方法来定义类。这个方法允许类加载器将字节码转换成Class
对象,而不需要委托给父类加载器。
4.调优类加载机制:
1.优化类加载性能:优化类加载性能可以通过减少类加载次数、优化类加载路径和使用自定义类加载器来实现。例如,可以通过预热类加载器来减少运行时的类加载次数。
2.减少类加载次数:通过分析应用程序的类加载模式,可以预先加载那些在运行时会被频繁加载的类。这可以通过在应用启动时执行一个“预热”过程来实现。
3.优化类加载路径:确保类路径(classpath)中只包含必要的JAR文件和类文件,可以减少类加载器的搜索时间。
4.使用自定义类加载器:自定义类加载器可以用于实现特定的类加载策略,例如按需加载类或者从特定的网络位置加载类。
5.监控和诊断:使用工具如jVisualVM、JConsole或者Java Mission Control来监控类加载活动。这些工具可以帮助识别类加载过程中的性能瓶颈。
5.结论
JVM的类加载机制是影响Java应用程序性能的关键因素。通过理解类加载的工作原理和调优类加载过程,开发者可以显著提升应用程序的性能。此外,合理利用类加载器和监控工具可以帮助开发者更有效地进行JVM调优。
后续会更新JVM内存模型,有兴趣的小伙伴可以关注一波!!!
标签:Java,jvm,自定义,应用程序,调优,JVM,父类,加载 From: https://blog.csdn.net/qq_74011163/article/details/142549484