JVM(二、类加载系统)

类加载器

JVM的类加载通过classLoader及其子类完成的

类加载器:

**启动类加载器(Bootstrap ClassLoader):**负责加载存放在 <JAVA_HOME>\lib 目录中的核心类库,如rt.jar、resources.jar等(或者被 -Xbootclasspath 参数所指定的路径中的,并且是虚拟机识别的类库)。这个加载器是 C++ 编写的,随着JVM启动。

**扩展类加载器(Extension ClassLoader):**负责加载<JAVA_HOME>\lib\ext 目录中的类库,(同样也可以用 java.ext.dirs 系统变量来指定路径)。

**应用程序类加载器(Application ClassLoader):**负责加载用户类路径 classpath 上所有的 jar 包和 .class 文件。

**自定义类加载器:**可以支持一些个性化的扩展功能(比如:JRebel)

类与类加载器

对于任意一个类,都需要由加载它的类加载器和这个类本身一同确立其在Java虚拟机中的唯一性,每一个类加载器,都拥有一个独立的类名称空间。

这句话可以表达得更通俗一些:比较两个类是否"相等",只有在这两个类是由同一个类加载器加载的前提下才有意义,否则,即使这两个类来源于同一个Class文件,被同一个虚拟机加载,只要加载它们的类加载器不同,那这两个类就必定不相等。

这里所指的"相等",包括代表类的Class对象的 equals() 方法、isAssignableFrom() 方法、isInstance() 方法的返回结果,也包括使用 instanceof 关键字做对象所属关系判定等情况。

类加载器执行顺序

加载时机和过程

类加载的四个时机:

  • 执行new、getStatic、putStatic、invokeStaic四条指令时
  • 使用java.lang.reflect包办法是,对类进行反射调用
  • 初始化一个类时,发现父类还没初始化,要先初始化父类
  • 当虚拟机启动时,用户需要指定一个主类main,需要先将主类加载

一个类的一生:

类加载做了什么

  1. 类全限定名称 -> 二进制字节流加载class文件
  2. 字节流静态数据 -> 方法区(永久代、元空间)
  3. 创建字节码Class对象

双亲委派

如果一个类加载器收到了类加载请求,它并不会自己先去加载,而是把这个请求委托给父类的加载器区执行,如果父类加载器还存在其父类加载器,则进一步向上委托,依次递归,请求最终将到达顶层的启动类加载器,如果父类加载器可以完成类加载任务,就成功返回,倘若父加载器无法完成此加载任务,子加载器才会尝试自己去加载,如果均加载失败,就会抛出ClassNotFoundException异常,这就是双亲委派模式。

双亲委派优点

安全 ,可避免用户自己编写的类动态替换Java的核心类,如java.lang.String。,java核心api中定义类型不会被随意替换,假设通过网络传递一个名为java.lang.Integer的类,通过双亲委托模式传递到启动类加载器,而启动类加载器在核心Java API发现这个名字的类,发现该类已被加载,并不会重新加载网络传递的过来的java.lang.Integer,而直接返回已加载过的Integer.class,这样便可以防止核心API库被随意篡改。
避免全限定命名的类重复加载(使用了findLoadClass()判断当前类是否已加载)。Java类随着它的类加载器一起具备了一种带有优先级的层次关系,通过这种层级关可以避免类的重复加载,当父亲已经加载了该类时,就没有必要子ClassLoader再加载一次。

相关推荐
whitepure9 小时前
万字详解JVM
java·jvm·后端
猿究院--王升2 天前
jvm三色标记
java·jvm·算法
静若繁花_jingjing2 天前
JVM常量池
java·开发语言·jvm
猿究院-赵晨鹤2 天前
JVM基础知识总结
java·jvm
代码输入中...2 天前
JVM常见面试题及答案
java·jvm·java面试·java面试题·jvm面试题
猿究院--冯磊2 天前
JVM垃圾收集器
java·jvm·算法
倒悬于世3 天前
JVM-类加载详情
java·开发语言·jvm
码熔burning3 天前
JVM 面试精选 20 题(续)
jvm·面试·职场和发展
完全学不完3 天前
JVM对象创建和内存分配
jvm