类加载器介绍

举报
共饮一杯无 发表于 2023/01/30 14:23:45 2023/01/30
【摘要】 名称加载哪的类说明BootStrap ClassLoader(启动类加载器)JAVA_HOME/jre/lib无法直接访问(C++代码书写的)Extension ClassLoader(扩展类加载器)JAVA_HOME/jre/lib/ext上级为BookStrap,显示为nullApplication ClassLoader(应用程序类加载器)classpath上级为Extension自定...
名称 加载哪的类 说明
BootStrap ClassLoader(启动类加载器) JAVA_HOME/jre/lib 无法直接访问(C++代码书写的)
Extension ClassLoader(扩展类加载器) JAVA_HOME/jre/lib/ext 上级为BookStrap,显示为null
Application ClassLoader(应用程序类加载器) classpath 上级为Extension
自定义类加载 自定义 上级为Application

启动类加载器

  • -Xbootclasspath表示设置bootclasspath
  • 其中/a:.将当前目录追加至bootclasspath之后
  • 可以用这个方法替换核心类
    • java -Xbootclasspath:<new bootclasspath>{解释:用新路径完全替换掉了原来路径JAVA_HOME/jre/lib}
    • java-Xbootclasspath/a:<追加路径>{解释:不替换原有路径,在原有路径追加路径a}
    • java- Xbootclasspath/p:<追加路径 >{解释:在原有路径上追加}
    1. 启动类加载非java实现,使用的 c/c++实现,嵌套在jvm内部

2.用于加载java的核心类库,用于提供jvm自身需要的类,比如rt.jar里面的类
3.不继承java.lang.ClassLoader,没有父加载器
4.负责加载扩展类加载器和系统应用类加载器,并为他们指定父加载器
5.出于安全考虑,该加载器只负责加载java,javax,sun等开头的类

扩展类加载器

  1. 是java语言编写,派生于ClassLoader类
  2. 父类加载器是启动类加载器
  3. 从java.ext.dirs系统属性所指定的目录中加载类库,或从jdk的安装目录下的jre/lib/ext子目录下加载类库,如果用户创建的 jar放在此目录下,也会有扩展类加载器来加载

应用程序类加载器

  1. 是java语言编写,派生于ClassLoader类
  2. 父类加载器是扩展类加载器
  3. 负责加载 环境变量classpath或者系统属性java.class.path路径下的类库
  4. 是程序中的默认加载器,一般来说,基本上java的类都是由它加载

自定义类加载器

为什么要定义自已的类加载器呢?

因为Java中提供的默认ClassLoader,只加载指定目录下的jar和class,如果我们想加载其它位置的类或jar时,就只能自定义一个ClassLoader类了。

比如:我要加载网络.上的一个class文件,通过动态加载到内存之后,要调用这个类中的方法实现我的业务逻辑。在这样的情况下,默认的ClassLoader就不能满足我们的需求了,所以需要定义自己的ClassLoader

如何定义类加载器?

继承ClassLoader类,重写findClass( )方法,loadClass( )方法
自定义类加载器注意事项:
自定义类加载器需要去继承ClassLoader类。

JDK1.2之前是重写ClassLoader类中的loadClass方法
JDK1.2以后 是重写ClassLader类中的findClass方法

自定义类加载器的实现,不要去覆盖ClassLoader类的loadClass方法,去实现findClass方法,为什么呢?

双亲委派机制

image.png

为什么要使用双亲委托这种模型呢?

考虑到安全因素,因为这样可以避免重复加载,当父亲已经加载了该类的时候,就没有必要子ClassLoader再加载一次 。
比如加载位于rt,jar包中的类java.lang.Object,不管是哪个加载器加载这个类,最终都是委托给顶层的启动类加载器进行加载,这样就保证了使用不同的类加载器最终得到的都是同样一个Object对象。
另外我们还可以试想一下,如果不使用这种委托模式,那我们就可以随时使用自定义的String来动态替代java核心api中定义的类型,这样会存在非常大的安全隐患,而双亲委托的方式,就可以避免这种情况,因为String已经在启动时就被引导类加载器(Bootstrcp ClassLoader)加载,所以用户自定义的ClassLoader永远也无法加载一一个 自己写的String,除非你改变JDK中ClassLoader搜索类的默认算法。

如何判定两个class是相同?

JVM在判定两个Class是否相同时,不仅要判断两个类名是否相同,而且要判断是否由同一个类加载器实例加载的。
Proxy.newProxyInstance(ClassI oader)

双亲委派机制源码

protected Class<?> loadClass(String name, boolean resolve)
 throws ClassNotFoundException
 {
    synchronized (getClassLoadingLock(name)) {
     // First, check if the class has already been
    loaded
     Class<?> c = findLoadedClass(name);
     if (c == null) {
     long t0 = System.nanoTime();
     try {
     if (parent != null) {
     c = parent.loadClass(name, false);
     } else {
     c =
    findBootstrapClassOrNull(name);
     }
     } catch (ClassNotFoundException e) {
     // ClassNotFoundException thrown if
    class not found
     // from the non-null parent class
    loader
     }
     if (c == null) {
     // If still not found, then invoke
    findClass in order
     // to find the class.
     long t1 = System.nanoTime();



     c = findClass(name);

     // this is the defining class loader;
    record the stats

    sun.misc.PerfCounter.getParentDelegationTime().addTime(t1
    - t0);

    sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFro
    m(t1);

    sun.misc.PerfCounter.getFindClasses().increment();
     }
     }
     if (resolve) {
     resolveClass(c);
     }
     return c;
     }
 }

本文内容到此结束了,
如有收获欢迎点赞👍收藏💖关注✔️,您的鼓励是我最大的动力。
如有错误❌疑问💬欢迎各位大佬指出。
保持热爱,奔赴下一场山海。🏃🏃🏃

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。