目录

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

1.1 什么是类加载

1.2 类加载的时机

1.3 类加载过程

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

1.3.2 链接

1.3.3 初始化

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

2.1 类的加载器有哪些

2.1.1 Bootstrap类加载器

2.1.2 Extension类加载器

2.1.3 Application类加载器

2.1.4 自定义类加载器

2.2 双亲委派机制

2.3 tomcat类加载器

三 如何自定义类加载器

3.1 继承ClassLoader

3.2 重写findClass方法


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

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;}
}

Java虚拟机专题之类加载机制相关推荐

  1. java 虚拟机类型的卸载_《深入理解Java虚拟机》:类加载和初始化(二)

    <深入理解Java虚拟机>:类加载和初始化(二) 在去年看<深入理解Java虚拟机>的时候,写过一篇关于类加载和初始化的博客,最近又在看这一块的知识,发现还是有很多东西没有理解 ...

  2. 深入理解Java虚拟机二(类加载器和类的加载过程)

    类加载器子系统作用 类加载器子系统负责从文件系统或者网络中加载Class文件,class文件在文件开头有特定的文件标识. ClassLoader只负责class文件的加载,至于它是否可以运行,则由Ex ...

  3. 【深入Java虚拟机】二 类加载与双亲委派

    https://blog.csdn.net/zhangliangzi/article/details/51338291  -参考 双亲委派过程:当一个类加载器收到类加载任务时,立即将任务委派给它的父类 ...

  4. 怎么把虚拟机清空内存_深入理解java虚拟机1——内存管理机制与回收机制

    文中涉及JVM底层知识大多来自<深入理解Java虚拟机>第2版,内容枯燥乏味,如果看,认真看.跟着撸一遍也可以受益良多. 1.JVM:是运行在操作系统之上的,它与硬件没有直接的交互. 运行 ...

  5. Java虚拟机10:类加载器

    类与类加载器 虚拟机设计团队把类加载阶段张的"通过一个类的全限定名来获取此类的二进制字节流"这个动作放到Java虚拟机外部去实现,以便让应用程序自己决定如何去获取所需要的类.实现这 ...

  6. Java虚拟机专题之class文件结构(读书笔记)

    我们知道一个Class文件对应着一个接口或者注解的类,但是他们并不一定定义在文件里,也可以直接由类加载器生成. Java虚拟机定义了专门的数据类型来表示class文件的内容,他们包括u1,u2,u4表 ...

  7. Java 虚拟机学习笔记 | 类加载过程和对象的创建流程

    前言 创建对象是 Java 语言绕不开的话题,那么对象是如何创建出来的呢?我们今天就来聊一聊.对象创建第一步就是检查类是否加载,而类的加载又牵扯到类的加载过程.如果单说对象的创建而绕开类的加载过程,感 ...

  8. 《深入理解Java虚拟机》内存管理机制 部分 读书笔记

    内存管理 运行时的数据区包括: 程序计数器 一块较小的内存空间,可以看作是当前线程所执行的字节码的行号指示器. 每个下次都需要有一个独立的程序计数器,各线程间计数器互不影响,独立存储. 如果线程执行的 ...

  9. Java语言学习之类加载机制与反射

    一.类的加载,连接和初始化 1.JVM和类 当调用java命令运行某个java程序时,该命令将会启动一个Java虚拟机进程,同一个JVM的所有线程,所有变量都处于同一个进程里,它们都使用该JVM进程的 ...

最新文章

  1. Ubuntu下开启SSH服务
  2. v7000更换电池步骤_v7000 gen1 电池更换问题
  3. Android手机系统adb常用的命令
  4. 说说 MySQL 子查询
  5. 在linux系统JDK安装中文字体
  6. 互联网巨头基于全球产业链打造ARM CPU
  7. 我那个37岁的大神朋友,后续
  8. 科学计算机fx-82es,fx-82ES PLUS A -2卡西欧计算器-计算器 函数科学-卡西欧官方商城...
  9. Hibernate面试总结
  10. AcWing 180. 排书
  11. RHEL 4 下 ISCSI Enterprise Target 的常用配置和常用操作
  12. 洛谷2543AHOI2005]航线规划 (树剖+线段树+割边思路)
  13. 分析EOF究竟是什么
  14. python打印星号图案_Python使用for循环打印星号三角形实例
  15. 前端面试你需要知道的事情:简历
  16. 数组的entries()方法
  17. 关于ADS的二次谐波和高次谐波牵引
  18. 3dsmax 选不中export,无法导出,选不中二级菜单
  19. 基于RSA+AES 软件授权License
  20. 「BJOI 2019」奥术神杖

热门文章

  1. excel取整函数_查询函数Choose、Lookup、Hlookup、Vlookup应用技巧解读
  2. mysql启动失败2005_数据库2005服务启动不了
  3. mac下nvm_【干货分享】Mac最全用法指导,学不会学费全退!!!(反正我也没收你们学费)...
  4. JavaScript常用工具Date对象和Math介绍介绍
  5. Java删除指定值结点[递归]图解
  6. 001redis数据库的介绍
  7. 唤起那些年你对IDL的记忆(二)
  8. asp.net如何解决传递中文参数乱码问题
  9. python数据预处理——数据分箱(将值归类)
  10. pytorch测试模型时根据不同列别的概率值得到具体的分类