jvm的类加载器,类装载过程

混沌初开,在一片名为jvm的世界中,到处都是一片虚无,直到一个名为BootstrapClassLoader的巨人劈开了世界,据说它是由名叫C++的女神所造,它从一个叫做jre/lib的宝袋中拿出一把开天之斧ExtensionClassLoader,以及其他各种各样五颜六色的宝物,这些宝物撒落在混沌世界中,
化作了山山水水.紧接着,巨人又使用ExtensionClassLoader这把巨斧劈开了一个叫做jre/lib/ext的巨峰,那里瞬间迸发出了五颜六色的彩芒,彩芒四溅而去,让这个灰色的世界不再那么暗淡.紧接着,名为BootStrapClassloader的巨人又将ExtensionClassLoader变成了一把宝剑,这把宝剑
名为ApplicationClassloader(其父类是ExtensionClassLoader),它光芒四射,巨人将它放入了一个名为环境变量的水池中,那里有一个身上刻着CLASSPATH的金鱼,巨人用宝剑插到了金鱼的身上,金鱼的血在宝剑上流动着,最后形成了串字符 D://myJavaClass/.之后宝剑爆发出了万丈光芒,这些光芒映照在天空之上,形成了以下
这些字:
一个类的加载过程分为:加载,验证,准备,解析,初始化
加载:顾名思义,就是根据类的全路径将类文件以二进制流的形式加载到内存中,当然,除了本地加载之外,jvm也支持从网络远程加载(需要自己实现类加载器)以及运行时动态生成(典型例子:动态代理),加载阶段,其实是我们自定义类加载器时最好控制的阶段,因为我们可以在findClass()方法里拿到class文件的二进制流后,自定义业务逻辑
之后将二进制流传入defineClass()方法.
验证:查看class文件数据是否符合规范以及是否会对jvm造成影响如:该类是否继承了被final修饰的类,类型转换是否正常(如:一个int不能强转为String),对于其他类属性的访问是否有权限(private,public)
准备:为内存中的静态成员变量分配空间,并赋默认值,但如果是被final 修饰的静态成员变量且其是基本数据类型或者字符串类型.也就给其赋值,并将其值存入静态常量池中.(前提条件是有静态且被final修饰的成员变量,并且它的赋值是基本数据类型或者字符串)
解析:将类成员变量和方法的字面量转换为直接引用也就是内存地址的过程(字面量是什么意思呢?好比你有个helloWorld()方法,此时这个方法的字面量就是helloWorld,如果是int a = 0,那么0就是字面量,记住,是字面量,但它不是具体值,因为值其实是一个内存地址),解析阶段不是必需的,如果你的类里没有静态成员变量或者方法就不会进行
初始化:在这个阶段,静态成员变量会被赋上我们开发人员定义的值,而此时如果有静态成员变量引用的是其它类的成员变量,或者是方法,或者直接就是new了,那么此时会去初始化其它类,而如果其它类里有反引用了本类,并且是静态成员变量,那么会直接调用本类的
构造方法,对本类进行初始化,再回到其它类.当然,这一切的前提是,如果此类有父类的话,那么必先初始化其父类.
其实初始化并非是一定触发的,但有3种必定会触发初始化
1:使用new关键字
2:通过反射机制也就是newInstance(),这里再拓展一点反射获取Class对象的知识1:getClass()此方法是通过对象头里的Class指针拿到的对应此对象的Class对象,此方法不会触发初始化,因为你都拿到对象了啊,已经初始化过了.2:类名.class,不会触发初始化机制,因为在编译阶段的时候class引用就被添加到静态常量池里了.3:Class.forName(),会触发静态代码块,因为这个方法会将类装载到内存中,并且初始化.
3:执行main方法的类
还有几种不会触发,1:我之前说的被final修饰的静态成员变量,并且值是字符串或者基本数据类型
2:子类通过父类直接拿父类的静态成员变量,不会触发子类的初始化,会触发父类的初始化,哪怕是被final修饰的静态成员变量,不过请注意的是,子类会被装载到内存中的.
3:被数组定义的类,如:Student[] stuArr = new Student[2];

最后,拓展一个知识点,JAVA还有一个线程加载器,可以实现单个线程内加载类.也就是不同的线程可以加载相同的类

原文地址:https://www.cnblogs.com/yangfeiORfeiyang/p/9380366.html

时间: 2024-08-06 09:57:48

jvm的类加载器,类装载过程的相关文章

JVM自定义类加载器加载指定classPath下的所有class及jar

一.JVM中的类加载器类型 从Java虚拟机的角度讲,只有两种不同的类加载器:启动类加载器和其他类加载器. 1.启动类加载器(Boostrap ClassLoader):这个是由c++实现的,主要负责JAVA_HOME/lib目录下的核心 api 或 -Xbootclasspath 选项指定的jar包装入工作. 2.其他类加载器:由java实现,可以在方法区找到其Class对象.这里又细分为几个加载器 a).扩展类加载器(Extension ClassLoader):负责用于加载JAVA_HOM

Java类装载过程

类装载过程由JVM类装载子系统负责,主要包括一下三个步骤: 1)装载:查找并装载类型的二进制数据到虚拟机中 1.通过某些途径,产生一个代表该类型的二进制数据流 2.解析二进制数据流为方法区的内部数据结构 3.在堆中创建一个表示该类型的Class实例(装载步骤的最终产品) 注意:Java虚拟机规范允许类装载器缓存Java类型的二进制表现形式,如果预装载出错,则要等待该类被主动使用时抛出LinkageError的子类的异常 2)连接: 1.验证 确保导入的类格式正确 检查final类不能有子类,fi

ClassLoader Java中类加载出现在哪个阶段,编译期和运行期? 类加载和类装载是一样的吗

1.ClassLoader Java中类加载出现在哪个阶段,编译期和运行期? 类加载和类装载是一样的吗? :当然是运行期间啊,我自己有个理解误区,改正后如下:编译期间编译器是不去加载类的,只负责编译而已,去rt.jar拿数据干嘛,不依然是class文件,jvm是只要是class文件就能运行. 2.类加载ClassLoader,各个类加载器执行顺序是什么? :永远是自己写的加载器先去加载,记住并不是真正的加载,而是双亲委派机制,每个加载器都不真正去加载,而是去让父加载器去加载,想一下,自然界亦是如

JVM之类加载器

一.首先,小小测试,看是否已经掌握了JVM类加载的过程 1.1.测试一: class Singleton { private static Singleton sin = new Singleton(); public static int counter1; public static int counter2 = 0; private Singleton() { counter1++; counter2++; } public static Singleton getInstance() {

【深入理解JVM】类加载器与双亲委派模型

原文链接:http://blog.csdn.net/u011080472/article/details/51332866,http://www.cnblogs.com/lanxuezaipiao/p/4138511.html 加载类的开放性 类加载器(ClassLoader)是Java语言的一项创新,也是Java流行的一个重要原因.在类加载的第一阶段"加载"过程中,需要通过一个类的全限定名来获取定义此类的二进制字节流,完成这个动作的代码块就是类加载器.这一动作是放在Java虚拟机外部

(转)JVM——自定义类加载器

背景:为什么要自定义,如何自定义,实现过程 转载:http://blog.csdn.net/SEU_Calvin/article/details/52315125 0. 为什么需要自定义类加载器 网上的大部分自定义类加载器文章,几乎都是贴一段实现代码,然后分析一两句自定义ClassLoader的原理.但是我觉得首先得把为什么需要自定义加载器这个问题搞清楚,因为如果不明白它的作用的情况下,还要去学习它显然是很让人困惑的. 首先介绍自定义类的应用场景: (1)加密:Java代码可以轻易的被反编译,如

java jvm虚拟机类加载器

在Java中任意一个类都是由这个类本身和加载这个类的类加载器来确定这个类在JVM中的唯一性. 类加载器 虚拟机设计团队把类加载阶段中的“通过一个类的全限定名来获取描述此类的二进制字节流”这个动作放到Java虚拟机外部去实现, 以便让应用程序自己决定如何去获取所需要的类. 实现这个动作的代码模块称为“类加载器”. 类与类加载器 类加载器虽然只用于实现类的加载动作, 但它在Java程序中起到的作用却远远不限于类加载阶段. 对于任意一个类, 都需要由加载它的类加载器和这个类本身一同确立其在Java虚拟

JVM 之类加载器

一.什么是 JVM JVM(Java Virtual Machine)是一个可以执行 Java 字节码文件(即 .class 文件)的虚拟机进程.当 Java 源文件能被成功编译成 .class 文件,就能在不同平台上的不同版本的 JVM 运行,因为 JVM 能将相同的 .class 文件解释称不同平台的机器码.正是因为 JVM 的存在,Java 被称为与平台无关的语言. 一般而言,.java 文件经过编译后会得到 .class 文件,而将这个文件加载到内存之前需要先通过类加载器,先简单过一下图

jvm自定义类加载器

除了自定义的类加载之外,jvm存在三种类加载器,并以一种父委托的加载机制进行加载. --启动类加载器,又称根加载器,是一个native的方法,使用c++实现.在java中我们用null标识,用于加载jdk自带的类. --扩展类加载器,用于加载jdk扩展类 --系统类加载器,用于加载classpath目录下的类 上面提到的三种类加载器,是存在父子关系,即系统类加载器会委托extension加载器,如果extension加载器不能加载该类的话,再由系统类加载器进行加载.注意这里所说的父子关系不是指继