JVM类加载过程分析

一.虚拟机启动:
1)命令启动 java -jar ***.jar
2)根据当前路径和系统版本,查找jvm.cfg配置
3)根据配置寻找jvm.dll并初始化虚拟机
4)调用JNIEnv接口查找Class文件

JNIEnv 是与线程有关的量,不同线程的JNIEnv彼此独立。
​有些认为JNIEnv是Java调用其他语言(通常是C/C++)的环境。

5)Bootstrap ClassLoader 加载Class文件在内存方法区中生成Class对象

负责加载$JAVA_HOME中jre/lib/rt.jar里所有的class,由C++实现,不是ClassLoader子类

6)Extension ClassLoader

负责加载java平台中扩展功能的一些jar包,包括$JAVA_HOME中jre/lib/*.jar或-Djava.ext.dirs指定目录下的jar包

7)App ClassLoader

负责记载classpath中指定的jar包及目录中class

8)Custom ClassLoader

属于应用程序根据自身需要自定义的ClassLoader

二.类加载过程:

  1. 装载
装载过程负责找到二进制字节码并加载至JVM中,JVM通过类名、类所在的包名通过ClassLoader来完成类的加载,同样,也采用以上三个元素来标识一个被加载了的类:类名+包名+ClassLoader实例ID。
  1. 链接
链接过程负责对二进制字节码的格式进行校验、初始化装载类中的静态变量以及解析类中调用的接口、类。
​完成校验后,JVM初始化类中的静态变量,并将其值赋为默认值。
​最后对类中的所有属性、方法进行验证,以确保其需要调用的属性、方法存在,以及具备应的权限(例如public、private域权限等),会造成NoSuchMethodError、NoSuchFieldError等错误信息。
  1. 初始化

初始化过程即为执行类中的静态初始化代码、构造器代码以及静态属性的初始化

1)调用了new
2)反射调用了类中的方法
3)子类调用了初始化
4)JVM启动过程中指定的初始化类

三.原则:
1.类是不会主动加载的,都是被动指定加载
2.类加载并不一定会初始化

被动引用
一、 通过子类引用父类的静态字段,不会导致子类初始化
二、 通过数组定义来引用类,不会触发该类的初始化
三、 常量在编译阶段会存入调用类的常量池中,本质上并没有直接引用到定义常量的那个类,所以也不会触发定义常量的类的初始化

3.类初始化有且只有以下5中情形常用4种:

遇到 new 如果类没有进行过初始化,则需要先触发其初始化。
使用 java.lang.reflect 包的方法对类进行反射调用的时候,如果类没有进行过初始化,则需要先触发其初始化。
当初始化一个类的时候,如果发现其父类还没有进行过初始化,则需要先触发其父类的初始化。
当虚拟机启动时,用户需要指定一个要执行的主类(包含main()方法的那个类),虚拟机会先初始化这个主类。

4.Java代码编译成字节码之后,是没有构造方法的概念的,只有类初始化方法 和 对象初始化方法 。

发布了66 篇原创文章 · 获赞 8 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq125281823/article/details/101476386