计算机系统应用教程网站

网站首页 > 技术文章 正文

jvm丨class的类加载机制

btikc 2024-09-08 12:00:28 技术文章 21 ℃ 0 评论

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


▲ class生存周期

加载(Loading)

1-通过类的全名(包名 + 类名),获取到该类的.class文件的二进制字节流。

2-将二进制字节流所代表的静态存储结构,转化为方法区运行时的数据结构。

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

验证(Verification)

确保class文件中字节流所包含的信息,符合当前JVM的要求,保证被加载class类的正确性,不会危害到JVM的安全。

准备(Preparation)

为类的静态变量分配存储空间,并设置默认的初始值。不包括实例变量,实例变量是在对象实例化后,随着对象一起分配到Java堆中。而类变量在JDK7之前存放在方法区中,而JDK7以后随着Class对象存放在Java堆中。

解析(Resolution)

将常量池中的符号引用替换为直接引用的过程,针对类或接口、字段、方法、接口方法、方法类型、方法句柄和调用点限定符进行引用。直接引用就是直接指向目标的指针、相对偏移量或一个间接定位到目标的句柄。

初始化(Initialization)

主要对类变量进行初始化操作,主要有两种方式:声明类变量指定初始值、使用静态代码块为类变量指定初始值。类的初始化(主动使用的六种)时机:1-new的方式、2-反射、3-初始化某个子类其父类会被初始化、4-访问类或接口的静态变量或对该静态变量赋值、5-调用类的静态方法、6-JVM启动时被标明启动类的类


类加载器的分类

▲ class加载器分类

  • 启动/引导类加载器(Bootstrap ClassLoader
      • 使用C/C++语言实现
      • 加载lib/rt.jar charset.jar 等核心类
  • 扩展类加载器(Extension ClassLoader
      • 使用Java语言编写,父类为java.lang.ClassLoader
      • 加载扩展jar包 jre/lib/ext/*.jar 或由 -D java.ext.dirs指定

  • 应用程序类加载器(Application ClassLoader
      • 使用Java语言编写,父类为java.lang.ClassLoader
      • 加载classpath指定内容


类加载过程如下图,当自定义类加载器(Custom)接收到类加载请求,从缓存读取是否已加载该类,如果没有则委托其父类(应用程序加载器APP)执行加载过程,如果父类可以完成加载任务,则返回成功结果,反之则重复上述过程,委托扩展类加载器(Ext)尝试加载,一直到启动类加载器(boot)尝试加载。

▲ class加载过程


总结:JVM类加载机制

  • 全盘负责,当一个类加载器负责加载某个Class时,该Class所依赖的和引用的其他Class也将由该类加载器负责载入,除非显示使用另外一个类加载器来载入
  • 父类委托,先让父类加载器试图加载该类,只有在父类加载器无法加载该类时才尝试从自己的类路径中加载该类
  • 缓存机制,缓存机制将会保证所有加载过的Class都会被缓存,当程序中需要使用某个Class时,类加载器先从缓存区寻找该Class,只有缓存区不存在,系统才会读取该类对应的二进制数据,并将其转换成Class对象,存入缓存区。这就是为什么修改了Class后,必须重启JVM,程序的修改才会生效
  • 双亲委派机制, 如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把请求委托给父加载器去完成,依次向上,因此,所有的类加载请求最终都应该被传递到顶层的启动类加载器中,只有当父加载器在它的搜索范围中没有找到所需的类时,即无法完成该加载,子加载器才会尝试自己去加载该类。

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表