您的位置:首页 > 其它

JVM核心之类加载器

2019-09-11 17:49 127 查看
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/weixin_43624024/article/details/100743697

类加载器的作用

将class字节码加载到内存,并将这些静态数据转换成方法区中的运行时数据结构,同时在堆中生成一个该类的java.lang.Class对象,用于访问方法区中的运行时数据结构。

类缓存

一旦某个类被加载到类加载器,它将维持加载一段时间,这也就是类缓存。若没有缓存机制,同一个类每次主动引用时都需要重新加载,太消耗时间和资源。
*JVM垃圾回收器可以回收这些Class对象。

类加载器层次结构

  • 启动类加载器:用来加载Java核心库(JAVA_HOME/jre/ext/rt.jar),用原生代码实现(C++),并不继承自java.lang.ClassLoader。
  • 扩展类加载器:用来加载Java扩展库(JAVA_HOME/jre/ext/*.jar),用Java代码实现,继承自java.lang.ClassLoader。
  • 应用程序类加载器:根据Java应用的类路径加载类,一般来说Java应用的类都是由它完成加载的,继承自java.lang.ClassLoader。
  • 自定义类加载器:开发人员可以通过继承Java.lang.ClassLoader类的方式实现自己的类加载器,用于满足一些特殊的需求。
public class Demo01 {
public static void main(String[] args) {
System.out.println(ClassLoader.getSystemClassLoader());
System.out.println(ClassLoader.getSystemClassLoader().getParent());
System.out.println(ClassLoader.getSystemClassLoader().getParent().getParent());
}
}

输出:

sun.misc.Launcher$AppClassLoader@18b4aac2//当前为应用程序类加载器
sun.misc.Launcher$ExtClassLoader@7f31245a//其父加载器为扩展类加载器
null//启动类加载器无法获取

java.lang.ClassLoader类

作用:根据一个指定类的名称,找到或者生成对应的.class字节码,然后通过这些字节码定义一个java.lang.Class类的实例

除此以外,ClassLoader还负责加载Java应用所需要的资源,如图像文件和配置文件等。

相关方法:
getParent() 返回该类加载器的父类加载器(启动类加载器无父类加载器)
loadClass(String name) 加载指定名称的类,返回结果为java.lang.Class类的实例
findClass(String name) 查找指定名称的类,若未加载则会加载该类,返回结果为java.lang.Class类的实例
findLoadClass(String name) 查找指定名称的已经被加载过的类,返回结果为java.lang.Class类的实例
defineClass(String name,byte[] b,int off,int len) 把字节数组b中的内容转换为Java类,返回结果为java.lang.Class类的实例
resolveClass<Class<?> class> 链接指定的Java类

类加载器的代理模式

当我们调用一个类加载器去加载一个类,当前的类加载器会交给其他类加载器去进行加载

双亲委托机制

其核心在于父类加载器优先加载,举个例子:我们通过一个自定义类加载器A去加载一个类,A会交给其父类加载器ApplicationClassLoader,ApplicationClassLoader又再交给其ExtensionClassLoader,ExtensionClassLoader又交给BootStrapClassLoader。BootStrapClassLoader负责加载核心库,加载失败交给子类加载器;ExtensionClassLoader负责加载扩展库,加载失败交给子类加载器;最后可能由ApplicationClassLoader或A进行加载,若直到加载器A都加载失败的话,则报错

这种机制的优点是:可以很安全的去加载相关的类,避免加载用户自己定义的java.lang.Object类。

例如我自己定义了一个java.lang.String类,调用类加载器加载时,优先交给BootStrapClassLoader,而在BootStrapClassLoader中检查到核心类库中存在已经加载好的String类,则不会再加载,一定程度上防止了危险代码的植入。

双亲委托机制是保证Java安全的核心机制,也是代理模式的一种
但并不是所有的类加载器都采用双亲委托机制,tomcat服务器类加载器也使用代理模式,不同的是它首先尝试去加载某个类,如果加载失败再代理给父类加载器。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: