一 类加载是什么?什么时候加载类?加载过程是怎么样的?

1.1 什么是类加载

类加载就是指将在硬盘上编译好的class字节码文件,加载到JVM内存中,然后对字节码文件进行链接和初始化的过程。只有加载后的字节码文件才可以被执行引擎解释和执行。

1.2 类加载的时机

JVM并不是启动的时候,就把全部的class字节码加载到内存,而是根据运行时候需要进行加载。比如没有加载到内存的类能够实例化吗?要访问静态类的变量或者方法,如果所在类没有被加载到内存,能访问静态变量和或者静态方法吗?
第一:创建类实例的时候,肯定要加载的,比如new、反射等
第二:访问类的静态变量或者静态方法
第三:加载子类的时候,父类也需要被加载,否则子类继承的父类属性或者方法有可能访问不到
第四:包含main方法的主类肯定也是要加载的

1.3 类加载过程

类的加载过程主要分为三个阶段: 加载、链接和初始化。

1.3.1 加载

第一:根据类的全限定名(包名+类名),获取二进制字节流
第二:将二进制字节流加载到内存,字节码文件中的常量池中的字面量如果是字符串则放到堆中字符串常量池,符号引号放到直接内存;静态变量和方法放入也放入堆中
第三:根据字节码信息创建Class对象放入到堆中

1.3.2 链接

链接主要是将目标文件链起来,和C/C++程序的链接要实现的效果是一样的,他主要包括三个阶段:验证、准备和解析

1.3.2.1 验证

第一: 验证class文件的格式。比如魔数、版本号大小
第二:验证元数据信息,比如继承的父类是否可以被继承;如果不是抽象类是否实现了所有的接口
第三:符号引用验证,是否可以根据全限定名找到对应的类,符号引用中的类的字段和方法是否可以被当前类访问

1.3.2.3 解析

解析就是将符号引用替换为直接引用的过程。在编译的时候无法确定引用对象的地址(还没有分配),是不知道实际的物理地址,所以才用一个唯一的符号来代替。而且经过验证过程知道符号引号的类是可以访问的到的,所以在解析这一步的时候直接将符号引号替换为真实的地址,这一步就是将目标文件链接起来了

1.3.3 初始化

执行类的初始化代码比如静态变量赋值或者执行静态代码块。初始化不是在准备阶段已经分配空间和给了默认值吗,但是注意,并没有在准备阶段执行初始化代码。比如这段代码:

public class JVMClient {private static long interval = Long.parseLong(System.getProperty("rebalance.interval"),20000);
}

interval 在准备阶段会在堆中分配8字节的内存,然后初始值为0,Long.parseLong(System.getProperty(“rebalance.interval”),20000);现在在在初始化阶段,则会执行后面的这段代码,比如rebalance.interval=10000,interval=10000

又比如这段代码,静态代码块也会在这个时候执行:

public class JVMClient {private static long interval = Long.parseLong(System.getProperty("rebalance.interval"),20000);private static List<String> nodeList;static {nodeList = getNodeList();}private static List<String> getNodeList() {return new ArrayList<String>();}
}

类初始化的时机,也可以说是类的加载时间,因为只要类被加载了肯定需要经历初始化阶段
第一:创建类实例的时候,需要加载类到JVM内存,然后就会经历链接和初始化阶段
第二:访问一个类的静态变量或者静态方法,需要加载类到JVM内存,然后这个类就会经历链接和初始化阶段
第三:加载一个类的时候,如果发现父类还没有加载,则也会加载父类并初始化父类
第四:main方法所在的类会被加载,所以也会初始化

二 类加载器有哪些?双亲委派模型的工作机制是怎样的?

2.1 类的加载器有哪些

2.1.1 Bootstrap类加载器

主要负责加载%JAVA_HOME%/lib下面的非ext包的所有类库,常用的java.util.、java.io.、java.lang.*都是由根加载器加载的

2.1.2 Extension类加载器

主要负责加载%JAVA_HOME%/lib/ext下面的所有扩展类库,比如内置的Javascript引擎、XML解析器等,这些类库以javax开头,它们的jar包位于%JAVA_HOME%/lib/ext目录中。

2.1.3 Application类加载器

主要负责加载应用程序classpath类路径上的类库,我们自己编写的代码以及引入的第三方JAR包都是由它来加载。

2.1.4 自定义类加载器

一般场景,使用Java默认的类加载器即可,但有时为了达到某种目的,又不得不实现自己的类加载器,例如为了使类库互相隔离,又或者为了实现热部署重加载功能,这时候就需要定义自己的类加载器,每一个类加载器加载各自的资源,以此达到资源隔离效果。可以沿用双亲委派机制,也可以打破这个机制。

2.2 双亲委派机制

第一:假设你的Application ClassLoader应用程序类加载器需要加载一个类,他不是自己去加载,而是先委托父类加载器Extension ClassLoader去加载
第二:Extension ClassLoader判断自己有父类加载器,则继续委托父类加载器Bootstrap ClassLoader去加载
第三:Bootstrap ClassLoader是根类加载器,没有父类加载器,则不再委托,它会在%JAVA_HOME%/lib/下去找要加载的类,
如果没有,则告诉Extension ClassLoader扩展类加载器没有找到
第四:Extension ClassLoader扩展类加载器则在%JAVA_HOME%/lib/ext目录下找,如果没有找到则告诉Application ClassLoader
应用程序类加载器
第五:应用程序类加载器则会在类路径下查找要加载的类

所以,这就输双亲委派模型,先找父类加载器要,没有则子类加载器自己找。这样可以避免多层级的类加载器重复加载某些类。
如果应用程序有类和%JAVA_HOME%/lib/或者%JAVA_HOME%/lib/ext下的类一样,则不会加载类路径下的类

2.3 tomcat类加载器

tomcat中拥有不同的自定义类加载器,以实现对各种资源的控制。一般来说,tomcat主要用类加载器解决以下四个问题:
#1 同一个web服务器,各个web项目之前各自使用的Java类库互相隔离
#2 同一个web服务器,各个web项目之间可以共享的Java类库
#3 服务器的类库与应用程序的类库互相独立
#4 对于支持JSP的web容器,应该支持热插拔的(HotSwap)功能

tomcat中最重要的类加载器是Common类加载器,他的父类是应用程序类加载器,负责加载CATALINA_BASE/lib,CATALINA_HOME/lib两个目录下所有的class文件和jar文件。

三 如何自定义类加载器

3.1 继承ClassLoader

3.2 重写findClass方法

public class MyClassLoader extends ClassLoader {//要加载的java类的classpath路径private String classPath;public MyClassLoader( String classPath) {super(ClassLoader.getSystemClassLoader());this.classPath = classPath;}@Overrideprotected Class<?> findClass(String name) throws ClassNotFoundException {byte[] data = this.loadData(name);//返回加载后的Class对象return this.defineClass(name, data, 0, data.length);}private byte[] loadData(String name) {try {name = name.replace(".", "/");FileInputStream is = new FileInputStream(new File(classPath + "/" +name + ".class"));ByteArrayOutputStream bos = new ByteArrayOutputStream();int b = 0;while ((b = is.read()) != -1) {bos.write(b);}is.close();return bos.toByteArray();} catch (Exception e) {e.printStackTrace();}return null;}public String getClassPath() {return classPath;}public void setClassPath(String classPath) {this.classPath = classPath;}
}

JVM专题之类加载机制相关推荐

  1. jvm运行时类加载机制_JVM体系结构:JVM类加载器和运行时数据区

    jvm运行时类加载机制 各位读者好! 在JVM系列的上一篇文章中,开发人员了解了Java虚拟机(JVM)及其体系结构. 本教程将帮助开发人员正确回答以下主题的问题: ClassLoader子系统 运行 ...

  2. JVM基础 - JAVA类加载机制

    JVM基础 - JAVA类加载机制 类的生命周期 其中类加载的过程包括了 加载 . 验证 . 准备 . 解析 . 初始化 五个阶段.在这五个阶段中, 加载 . 验证 . 准备 和 初始化 这四个阶段发 ...

  3. 深入理解JVM(5)——虚拟机类加载机制

    在Class文件中描述的各种信息,最终都需要加载到虚拟机中之后才能运行和使用.而虚拟机中,而虚拟机如何加载这些Class文件?Class文件中的信息进入到虚拟机中会发生什么变化?本文将逐步解答这些问题 ...

  4. 【深入理解JVM】ClassLoader类加载机制

    Java程序并不是一个原生的可执行文件,而是由许多独立的类文件组成,每一个文件对应一个Java类.此外,这些类文件并非立即全部装入内存的,而是根据程序需要装入内存.ClassLoader专门负责类文件 ...

  5. jvm(7)-虚拟机类加载机制

    [0]README 0.1)本文转自"深入理解jvm",旨在学习  虚拟机类加载机制 的基础知识: [1]概述 1)类加载机制:虚拟机把描述类的数据从Class 文件加载到内存,并 ...

  6. fegin需要实现类_深入理解JVM(六)--虚拟机类加载机制

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

  7. [JVM]了断局: 类加载机制

    一.类加载的时机 二. 有且只有六种情况必须立即对类进行"初始化" 三.类加载的过程 1.加载 2.验证 1.文件格式验证 2.元数据验证 3.字节码验证 4.符号引用验证 3.准 ...

  8. 深入理解JVM之虚拟机类加载机制

    1.概述 Java虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这个过程被称作虚拟机的类加载机制.与那些在编译时需要进 ...

  9. Java虚拟机专题之类加载机制

    目录 一 类加载是什么?什么时候加载类?加载过程是怎么样的? 1.1 什么是类加载 1.2 类加载的时机 1.3 类加载过程 类的加载过程主要分为三个阶段: 加载.链接和初始化.1.3.1 加载 1. ...

最新文章

  1. Maven出现错误No plugin found for prefix ‘jetty‘ in the current project and in the plugin groups的问题解决
  2. Angular2视图操作之ViewChildViewChildren
  3. max7219驱动共阳点阵
  4. C语言EOF是什么?
  5. 机器学习实战 - 读书笔记(04) - 朴素贝叶斯
  6. SpringBoot—启动报错Exception in thread “main“ java.lang.ClassNotFoundException
  7. VPP 安装配置工具vpp-config
  8. Javascript 调用百度地图不显示
  9. 扫地机自动回充揭秘之小米/iRobot/云鲸/360
  10. 【操作系统/OS笔记11】并发执行的必要性,产生的问题,原子操作,为什么引入锁机制,面包购买的类比
  11. knn算法的最佳k值_KNN(k-NearestNeighbor)算法笔记
  12. 秒杀服务,秒杀系统设计与实现
  13. 高冷一字id_一个字网名 高冷一字id
  14. 百度地图爬虫——小试牛刀
  15. 磁盘最优存储问题---Python
  16. 无人机基于目标检测的路径规划任务
  17. 如何搭建简易又安全的企业内部文件服务器?
  18. android腾讯新闻,Android实现腾讯新闻的新闻类别导航效果
  19. 区块链创业者惠轶之死
  20. [CTF]中那些脑洞大开的编码和加密

热门文章

  1. 第二篇:稳定性之如何有条不紊地应对风险?
  2. 5-1计算机视觉的基本概念
  3. oracle数据库匿名快,pl/sql分匿名块和命名块
  4. 学期计算机教案,学年第2学期课程教案-计算机组成原理-陈立伟
  5. java提升权限运行_提升代码的运行权限,实现模拟管理员身份的功能
  6. python怎样创建桌面快捷方式_python创建桌面快捷方式的代码
  7. Matlab x2fx函数
  8. 升级php5.4 mysql5.5_在CentOS上把PHP从5.4升级到5.5
  9. java数组表格输出_Java 如何将数组中的数据以表格形式输出
  10. 台式计算机主机组成图,台式电脑主板的各部分组成及详细说明,还有各种连...-卓优商学问答...