虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是虚拟机的类加载机制。

  类加载的时机:类从被加载到虚拟机的内存中,到卸载内存为止,它的整个生命周期包括:加载、验证、准备、解析、初始化、使用和卸载7个阶段。其中验证、准备、解析3个部分统称为连接。

本篇只叙述类加载过程中的加载、初始化阶段以及类加载器和双亲委派模型。

什么时候加载?

Java虚拟机规范中并没有进行强制约束,这点可以交给虚拟机的具体实现来自由把握。

什么时候初始化?

  1.遇到new、getstatic、putstatic或invokestatic这4条指令时,如果类没有进行过初始化,则需要先触发其初始化。

  2.使用java.lang.reflect包的方法对类进行反射调用的时候,如果类没有进行过初始化,则需要先触发其初始化。

  3.当初始化一个类的时候,如果发现其父类还没有进行过初始化,则需要先触发其父类的初始化。

  4.当虚拟机启动时,用户需要指定一个要执行的主类(包含main()方法的类),虚拟机会先初始化这个类。

  5.当使用JDK1.7的动态语言支持时,如果一个java.lang.invoke.MethodHandle实例最后的解析结果REF_getstatic、REF_putstatic、REF_invokestatic的方法句柄,并且这个方·    法句柄所对应的类没有进行过初始化,则需要先触发其初始化。

代码:

package com.shamgod.classload;
/*** 将被初始化的类* @author ShammGod**/
public class ClassLoad1 {static int i = 1;static {System.out.print(ClassLoad1.class + " 被初始化了!");}static void info() {System.out.println("I'm a class");}
}

情况1:

package com.shamgod.classload;
/*** 类初始化测试类* @author ShammGod**/
public class TestClassLoad {public static void main(String[] args) {//new指令ClassLoad1 classLoad1 = new ClassLoad1();//输出:class com.shamgod.classload.ClassLoad1 被初始化了!
    }
}

 1 package com.shamgod.classload;
 2 /**
 3  * 类初始化测试类
 4  * @author ShammGod
 5  *
 6  */
 7 public class TestClassLoad {
 8
 9     public static void main(String[] args) {
10
11         //getstatic指令
12         System.out.println(ClassLoad1.i);
13         //输出:class com.shamgod.classload.ClassLoad1 被初始化了!1
14     }
15 }

 1 package com.shamgod.classload;
 2 /**
 3  * 类初始化测试类
 4  * @author ShammGod
 5  *
 6  */
 7 public class TestClassLoad {
 8
 9     public static void main(String[] args) {
10
11         //putstatic指令
12         ClassLoad1.i = 20;
13         //输出:class com.shamgod.classload.ClassLoad1 被初始化了!
14     }
15 }

 1 package com.shamgod.classload;
 2 /**
 3  * 类初始化测试类
 4  * @author ShammGod
 5  *
 6  */
 7 public class TestClassLoad {
 8
 9     public static void main(String[] args) {
10
11         //invokestatic指令
12         ClassLoad1.info();
13         //输出:class com.shamgod.classload.ClassLoad1 被初始化了!I'm a class
14     }
15 }

情况2:

package com.shamgod.classload;import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;/*** 类初始化测试类* @author ShammGod**/
public class TestClassLoad {public static void main(String[] args) throws Throwable {//反射获取该ClassLoad1类的类对象Class class1 = ClassLoad1.class;//得到该类对象的所有字段Field[] fields = class1.getDeclaredFields();for (Field field : fields) {//使用java.lang.reflect包的Field类的get()方法进行反射调用,触发初始化
            System.out.print(field.get(class1));//输出:class com.shamgod.classload.ClassLoad1 被初始化了!1
        }}
}

情况3:

 1 package com.shamgod.classload;
 2 /**
 3  * 将被初始化的类
 4  * @author ShammGod
 5  *
 6  */
 7 public class ClassLoad1 {
 8
 9     static int i = 1;
10     static {
11         System.out.print(ClassLoad1.class + " 被初始化了!");
12     }
13
14     static void info() {
15         System.out.println("I'm a class");
16     }
17 }
18 class ClassLoad2 extends ClassLoad1{
19     static {
20         System.out.println(ClassLoad2.class + " 被初始化了!");
21     }
22 }

 1 package com.shamgod.classload;
 2
 3 /**
 4  * 类初始化测试类
 5  * @author ShammGod
 6  *
 7  */
 8 public class TestClassLoad {
 9
10     public static void main(String[] args){
11         ClassLoad2 classLoad2 = new ClassLoad2();
12     }
13 }

情况4:

 1 package com.shamgod.classload;
 2
 3 /**
 4  * 类初始化测试类
 5  * @author ShammGod
 6  *
 7  */
 8 public class TestClassLoad {
 9     //执行主类的静态代码块,类加载过程中的初始化阶段会执行该代码块
10     static {
11         System.out.print("我是一个要执行的主类(我有main方法!)");
12     }
13
14     public static void main(String[] args){
15         System.out.print("main方法执行了!");
16     }
17     //输出:我是一个要执行的主类(我有main方法!)main方法执行了!
18 }

情况5:TODO

加载:“加载”是“类加载”过程的一个阶段,在加载阶段需要完成3个步骤:

1.通过一个类的全限定名来获取定义此类的二进制字节流。

2.将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。

3.在内存中生成一个代表代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口。

初始化:类初始化阶段是类加载过程的最后一步,前面的类加载过程中,除了在加载阶段用户应用程序可以通过自定义类加载器参与之外,其余动作完全由虚拟机主导和控制。到了初始化阶段,才真正开始执行类中定义的Java程序代码。

类加载器:虚拟机设计团队把类加载阶段中的“通过一个类的全限定名来获取定义此类的二进制字节流”这个动作放到Java虚拟机外部去实现,以便让应用程序自己决定如何去获取所需要的类。实现这个动作的代码模块称为:“类加载器”。

双亲委派模型:

启动类加载器(Bootstrap ClassLoader):负责将存放在<JAVA_HOME>\lib目录中的,或者被-Xbootclasspath参数所指定的路径中的,并且是虚拟机识别的(仅按照文件名识别,如rt.jar,名字不符合的类库即使放在lib目录中也不会被加载)类库加载到虚拟机内存中。

扩展类加载器(Extension ClassLoader):负责加载<JAVA_HOME>\lib\ext目录中的,或者被java.ext.dirs系统变量所指定的路径中的所有类库,开发者可以直接使用扩展类加载器。

应用程序类加载器(Application ClassLoader):负责加载用户类路径(classpath)上的指定类库,我们可以直接使用这个类加载器。一般情况,如果我们没有自定义类加载器默认就是用这个加载器。

双亲委派模型工作过程是:如果一个类加载器收到类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器完成。每个类加载器都是如此,只有当父加载器在自己的搜索范围内找不到指定的类时(即ClassNotFoundException),子加载器才会尝试自己去加载。

          

双亲委派模型的好处:

Java类随着他的类加载器一起聚类了带有优先级的层次关系。无论哪个类加载器要加载这个类最终都会传递到最顶层的启动类加载器,再向下逐层尝试,这就能保证所有相同的类在各种类加载器环境中都是同一个类,若没有类似的向上传递的过程,由各个类加载器自行去加载的话,系统中会出现多个不同的一个名称的类,各种类的行为无法保证一致,体系崩坏。

转载于:https://www.cnblogs.com/shamgod-lct/p/9341574.html

JVM类加载机制(加载,初始化,类加载器和双亲委派机制)相关推荐

  1. 深入JVM系列(三)之类加载、类加载器、双亲委派机制与常见问题

    转载自 深入JVM系列(三)之类加载.类加载器.双亲委派机制与常见问题 一.概述 定义:虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用 ...

  2. JVM学习笔记-03-类加载器及双亲委派机制

    JVM学习笔记-03-类加载器及双亲委派机制 文章目录 JVM学习笔记-03-类加载器及双亲委派机制 1. 类加载器 视频链接-最新JVM教程IDEA版[Java面试速补篇]-03-类加载器及双亲委派 ...

  3. java 类加载 双亲委派_Java类加载器和双亲委派机制

    前言 之前详细介绍了Java类的整个加载过程(类加载机制详解).虽然,篇幅较长,但是也不要被内容吓到了,其实每个阶段都可以用一句话来概括. 1)加载:查找并加载类的二进制字节流数据. 2)验证:保证被 ...

  4. 打破双亲委派机制有什么用_1.4 打破双亲委派机制

    什么是打破双亲委派机制呢? 那么这里第一步, 我们需要知道什么是双亲委派机制? 前面已经说了什么是双亲委派机制了, 那打破是怎么回事呢? 比如, 我现在有一个自定义类加载器, 加载的是~/com/lx ...

  5. JVM入门(位置、体系结构、类加载器、双亲委派机制、沙箱安全机制、Native、PC寄存器、方法区、堆(新生区{伊甸园区、幸存区}、养老区、永久区)、OOM、GC算法、JMM)

    目录 一.JVM的位置 二.JVM的体系结构 三.类加载器 1.类加载器举例 2. JVM中提供了三层的ClassLoader 3. 双亲委派机制(重要) 3.1 工作原理 3.2.优点 四.沙箱安全 ...

  6. 【JVM】类加载器:双亲委派机制、沙箱安全机制

    · 双亲委派机制.沙箱安全机制是JVM中类加载器系统的相关术语 · 在这之前,应该先了解JVM类加载器系统的相关概念 一.类加载器基础知识 见下图1,java文件首先会被编译成class文件,clas ...

  7. android双亲委派机制,类加载器及双亲委派机制

    一. 类的加载 java class是由class loader 类加载器加载到JVM内存中的. 看下下面的demo,java中有三种类加载器. 首先,我们自己定义的这个classLoaderDemo ...

  8. JVM(1)之JVM的组成详解(字符串常量池+双亲委派机制+JIT即时编译......)

    以下总结自:<深入理解java虚拟机> + 宋红康老师视频 字节码文件介绍:深入理解JVM之Java字节码(.class)文件详解_Windy_729的博客-CSDN博客_字节码文件 JV ...

  9. java的双亲委派_深入理解Java的类加载器及双亲委派机制

    当我们在写完一个Java文件的时候,编译器会将.java文件编译成.class文件,然后当程序运行时,JVM首先会找到main方法所在类,并将main所在类的class文件字节码读到内存中,转换成JV ...

  10. JVM类加载机制、双亲委派机制、自定义类加载器、打破双亲委派机制

    1.类加载器 站在Java虚拟机的角度看,只有两种不同的类加载器:一种是启动类加载器(Bootstrap ClassLoader),这个类加载器使用C++语言实现(HotSpot虚拟机.JDK8中), ...

最新文章

  1. python csv读取-python如何读取csv数据
  2. win10下linux子系统6,Windows10下安装Linux子系统2020年7月最新版
  3. case class到底啥用
  4. flask 获取前端form内容_flask 项目中使用 bootstrapFileInput(进阶篇)
  5. 35岁前需要完成的事
  6. MySQL建表时Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP
  7. 《C++ Primer》读书笔记—第六章 函数
  8. 全网首发:FFMpeg使用NVIDIA DECODER,解码后的数据是NV12,不是YUV420P
  9. .net程序员转战android第二篇---牛刀小试
  10. TeeChart Pro Activex 2022.1/32/64/Crack
  11. 洋桃开发板笔记(五 ) Flash闪存的使用
  12. 计算机断电会自动重启吗,电脑开机断电或自动重启的分析及解决方法
  13. 2018软工—团队现场编程实战(抽奖系统)
  14. 未睹棺椁先哭君——谷歌墓志铭
  15. 万豪酒店Marriott 积分兑换标准房晚必备:全球 Marriott Cat9 等级酒店列表 汇总
  16. 莫队算法二(树上莫队cot2,Haruna’s Breakfast)
  17. 【Cadence17.2】Padstack Editor制作焊盘和过孔
  18. 实例分割总结 Instance Segmentation Summary
  19. PMP系列 - 关键链法
  20. (八)二叉树—线索二叉树

热门文章

  1. 贝多芬交响曲全集(转)
  2. python中缺省值处理函数DataFrame.fillna()
  3. 基于STM32HAL库ADS1256调试笔记
  4. Data‘ object has no attribute ‘has_isolated_nodes
  5. python中等好用什么表示_描写中等的词语
  6. 688. 骑士在棋盘上的概率(中等 动态规划)
  7. 在 Ubuntu 中安装 Firefox
  8. 如何提高Python编程能力?
  9. 练习4-10 找出最小值 (20分) 本题要求编写程序,找出给定一系列整数中的最小值。
  10. 接受自己平庸真的很难吗?你知道163邮箱登陆界面是什么吗?