了解JVM:类加载机制

class加载过程

类加载器加载,采用双亲委派机制

  1. Loading 加载:将class文件加载到内存
  2. Linking 链接
    1. Verification 验证:验证加载的class是否符合class文件标准(如:前4字节是否是cafebabe)
    2. Preparation 准备:给静态变量赋默认值等
    3. Resolution 解析:将类、方法、属性等符号引用解析为直接引用(常量池中的各种符号引用解析为指针、偏移量等内存地址的直接引用)
  3. Initializing 初始化:给静态变量赋初始值、执行静态代码块等(调用类初始化代码<clinit>)

类加载器(ClassLoader)

负责将class加载到内存

  1. 将class文件二进制数据加载到内存
  2. 解析二进制数据生成对应Class对象
  3. 默认采用懒加载方式,且只加载一次
  1. BootstrapClassLoader:负责加载lib/rt.jar charset.jar等核心类,C++实现
    1. 查看加载路径:System.getProperty(“sun.boot.class.path”)
    2. 这个类加载器加载的class,getClassLoader方法返回为null
  2. ExtClassLoader:负责加载扩展jar,jre/lib/ext/*.jar
    1. 查看加载路径:System.getProperty(“java.ext.dirs”)
  3. AppClassLoader:加载classpath中的class,通常指应用程序中定义的class
    1. 查看加载路径:System.getProperty(“java.class.path”)
  4. 自定义ClassLoader:应用程序自己定义的ClassLoader

双亲委派机制

  1. 父 -> 子:BootstrapClassLoader -> ExtClassLoader -> AppClassLoader
  2. 这里的父子不是继承关系,而是子加载器内聚父加载器(子加载器成员变量parent指向父加载器)
  1. 对双亲的理解:
    1. 既有子到父的过程也有父到子的过程?
    2. BootstrapClassLoader和ExtClassLoader是AppClassLoader的双亲?
  2. 当需要加载一个class时,由AppClassLoader进行加载(这里不考虑自定义类加载器)
  3. AppClassLoader不会直接加载,而是先检查自己是否已经加载过这个类,如果已加载则直接返回,否则交给ExtClassLoader进行处理
  4. 同样ExtClassLoader也不会直接加载,而是先检查自己是否已经加载过这个类,如果已加载则直接返回,否则交给BootstrapClassLoader进行处理
  5. BootstrapClassLoader先检查是否自己已经加载过这个类,如果已加载则直接返回,如果没有加载过,由于BootstrapClassLoader没有父加载器,所以会尝试在自己负责的类路径中查找对应的类,如果找到则进行加载并返回,如果没有找到则向下交给ExtClassLoader
  6. ExtClassLoader发现BootstrapClassLoader返回为null,则会尝试在自己负责的类路径中查找对应的类,如果找到则进行加载并返回,如果没有找到则向下交给AppClassLoader
  7. AppClassLoader同理,如果最终都没成功加载,则会抛出ClassNotFound异常
  8. 为什么使用双亲委派?
    1. 可以防止重复加载(优先从缓存中查找是否已加载过)
    2. 保证JDK核心类的优先加载
    3. 举例:假如应用程序也创建了java.lang.String这样的类,如果不用双亲委派,那么java核心库中的java.lang.String可能会被覆盖,从上面的加载流程可知,双亲委派机制中父加载器的加载逻辑会优先执行,所以java.lang.String这个类只会被BootstrapClassLoader加载,因为这个类存在于BootstrapClassLoader负责的类路径中
  9. 打破双亲委派机制?
    1. 自定义类加载器:继承ClassLoader,重写loadClass方法
    2. 典型场景1:Tomcat部署多个应用处于同一JVM虚拟机进程,假如不同应用间使用了同一个类的不同版本,就会发生冲突,所以需要自定义ClassLoader并打破双亲委派
    3. 典型场景2:热部署实现

自定义ClassLoader

自定义类加载路径,或直接加载指定的二进制数据等
比如:加载自己加密的class,可以防止class文件被篡改或反编译

  1. 继承ClassLoader
  2. 重写loadClass、findClass等方法
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值