计算机系统应用教程网站

网站首页 > 技术文章 正文

深入理解Java类加载机制-类加载器

btikc 2024-11-02 11:09:18 技术文章 9 ℃ 0 评论

加载作为类加载的第一个阶段,是开放的,它允许Java程序员通过自定义的类加载器去加载特定的类。

对于任意一个Java类,都需要加载它的类加载器和这个类本身确定唯一性。言外之意:比较两个类是否相等(Class对象的equal()、isAssignableFrom()方法、isInstance()方法和instanceof关键字),如果两个类不是由同一类加载器加载,那么他们必然不想等,如果两个类由同一加载器加载,才有可能相等。

1. 类加载器

在实际开发中,我们很少会去定义自己的类加载器,因为Java本身自带了三种类加载:

  • 启动类加载器(BootstrapClassLoader)
  • 扩展类加载器(ExtClassLoader)
  • 应用程序类加载器(AppClassLoader)

1.1 启动类加载器

启动类加载器使用C++语言实现,是虚拟机自身的一部分,负责对存放在<JAVA_HOME>/lib目录或通过-Xbootclasspath参数所指定的路径中的jar包文件进行加载,并且只有文件名可被虚拟机识别(例如rt.jar)加载到虚拟机内存中。

启动类加载器不能被Java程序直接引用。

除了启动类加载器,其他加载器均由Java语言实现,独立于JVM。

1.2 扩展类加载器

扩展类加载器由sun.misc.Lanuncher$ExtClassLoader类实现,负责加载<JAVA_HOME>/lib/ext目录或被系统变量java.ext.dirs所指定的路径中的所有类库,开发者可以直接使用扩展类加载器。

1.3 应用程序类加载器

应用程序类加载器由sun.misc.Lanuncher$AppClassLoader类实现,负责加载用户类路径上所指定的类库。这个类加载器可以通过ClassLoader.getSystemClassLoader()方法直接获得,所以一般也称该类加载器为系统加载器

2. 双亲委派机制

有了以上三种类加载器和我们自定义的加载器,那么我们该如何搭配使用他们呢?

在Java中并没有一些强制性约束,但是双亲委派机制是Java设计者推荐给开发者的一种类加载器使用方式。

双亲委派机制要求除了启动类加载,其他加载都需要有自己的父类加载器,在实现方面,不采用继承而是采用组合的形式。

类加载器在收到一个类的加载请求后,不会主动去加载这个类,而是将类的加载请求委托给父类加载器,只有当父类加载无法完成加载的时候才由自身去加载。

由于上述加载过程的存在,所有的类都会传递到启动类加载中尝试加载。这种机制的好处就是:假设有人恶意编写了一个和Java类包名类名一模一样的类(这里假设是java.lang.Object),由于类的加载请求会被传递到启动类加载器中尝试加载,当启动类加载器尝试加载的时候实际是加载的在<JAVA_HOME>/lib的中的java.lang.Object,因此这个恶意的类永远不会被加载,双亲委派模型一定程度上保证了Java程序的安全运行。

3. 类加载方式

类的加载方式有三种:

  • 命令启动的时候由JVM加载
  • 通过Class.forName()方法加载
  • 通过ClassLoader.loadClass()方法加载,这个需要一个ClassLoader实例

Class.forName():将class文件加载到JVM中,并且初始化类(执行static语句块)

ClassLoader.loadClass():将class文件加载到JVM中,不进行初始化,不执行static语句块,只有newInstance的时候才会执行static语句块

Class.forName(name, initialize, loader):Class.forName()的参数版本,initialize参数可以控制是否初始化类(执行static语句块, true为初始化,false不初始化),loader可以指定类加载器。

本期类加载器介绍到这,下期我们实现一个自定义的类加载器,我们下期再见!!!

我是shysh95,希望可以和你专注技术的路上并肩作战,搜索关注微信公众号:Different Java,更多精彩文章!!!

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

欢迎 发表评论:

最近发表
标签列表