本站消息

站长简介/公众号

  出租广告位,需要合作请联系站长


+关注
已关注

分类  

暂无分类

标签  

暂无标签

日期归档  

2024-11(3)

JVM——类加载器详解

发布于2020-12-23 21:30     阅读(789)     评论(0)     点赞(10)     收藏(1)


类加载器的分类

上图中箭头并不代表继承关系,是上下层关系

  • JVM支持两种类型的类加载器
    • 引导类加载器(Bootstrap Classloader):C和C++编写的,
    • 自定义类加载器(User-defined Classloader):Java语言编写的
      • 严格定义上,拓展类加载器(Extension Classloader)和系统类加载器(System Classloader)都是抽象类ClassLoader的派生类加载器(两者都间接继承了ClassLoader),归为自定义类加载器

  • 获取不到C语言编写的bootstrap classloader
  • 用户定义类默认使用的是系统类加载器加载的
  • 系统的核心类库是使用启动类加载器加载的

启动类加载器

又叫引导类加载器(bootstrap classloader)

  • 使用C&C++编写,嵌套在JVM内部,不在Java本身的范畴之内,同理就是和ClassLoader抽象类没有任何直接的关系
  • 用来加载Java的核心类库(JAVA_HOME/jre/lib/rt.jar&resources.jar或者是sun.boot.class.path路径下的内容),也用于提供JVM自身所需要的类
    • 处于安全的考虑,只加载包名以java、javax、sun开头的类
  • 加载拓展类加载器(Extension Classloader)和系统类加载器(System Classloader),并指定为他们的父加载器

拓展类加载器

  • Java语言编写,由sun.misc.Launcher$ExtClassLoader实现,间接继承ClassLoader
  • 父类加载器是启动类加载器(bootstrap classloader),这里的父类并不是父子类关系,而是层级关系
  • 由系统属性java.ext.dirs指定的目录中加载类库,或者从JDK安装目录JAVA_HOME/jre/lib/ext(扩展目录)下加载类库(开发者的jar文件放在该目录下,自动由拓展类加载器加载)

系统类加载器

又成为应用程序类加载器

  • Java语言编写,由sun.misc.Launcher$AppClassLoader实现,间接继承ClassLoader
  • 父类加载器是拓展类加载器
  • 负责加载环境变量classpath或者系统属性java.class.path执行下的类库
  • 该类加载器是程序中默认的加载器(开发者提供的类)

自定义类加载器

开发者自己提供的加载器,通过继承java.lang.ClassLoader来自定义类加载器:JDK1.2远古时期,继承ClassLoader之后重写loadClass()方法,JDK1.2之后建议开发者把自定义类加载的逻辑代码重写在findClass()方法中(这个方法需要开发者自己读取字节码文件,加密的字节码文件就可以在这里解密并加载)。如果没有很特别的需求,可以直接继承URLClassLoader,这样可以省略编写findClass()方法以及其获取字节码文件流的过程。

什么情况下需要自定义加载器

  • 隔离加载类:可以用来将应用和中间件相关的jar包分开,以免引入的包有冲突(程序中各种框架依赖的jar包可能有冲突)
  • 修改类的加载方式
  • 拓展加载源:一般来说是从系统磁盘的class文件或者jar包加载,自定义类加载器可以拓展为从数据库中加载等
  • 防止源码泄露:对字节码文件加密,自定义类加载器在加载字节码文件之前先解密

相关测试验证

  1. package com.leolee.multithreadProgramming;
  2. import lombok.extern.slf4j.Slf4j;
  3. import sun.misc.Launcher;
  4. import java.net.URL;
  5. /**
  6. * @ClassName Test
  7. * @Description: TODO
  8. * @Author LeoLee
  9. * @Date 2020/12/1
  10. * @Version V1.0
  11. **/
  12. @Slf4j
  13. public class Test {
  14. public static void main(String[] args) throws InterruptedException {
  15. //系统类加载器
  16. ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
  17. System.out.println(systemClassLoader);
  18. //拓展类加载器
  19. ClassLoader extClassLoader = systemClassLoader.getParent();
  20. System.out.println(extClassLoader);
  21. //启动类加载器
  22. ClassLoader bootstrapClassLoader = extClassLoader.getParent();
  23. System.out.println(bootstrapClassLoader);
  24. //用户定义类默认使用系统类加载器
  25. ClassLoader classLoader = Test.class.getClassLoader();
  26. System.out.println(classLoader);
  27. //Java的核心类库都是使用引导类加载器加载的
  28. ClassLoader classLoader1 = String.class.getClassLoader();
  29. System.out.println(classLoader1);
  30. //启动类加载器加载的类库的路径
  31. //这些路径下的类,获取其加载器的时候都是null
  32. URL[] urLs = Launcher.getBootstrapClassPath().getURLs();
  33. for (URL url : urLs) {
  34. System.out.println(url.toExternalForm());
  35. }
  36. //拓展类加载器加载类库的路径
  37. String property = System.getProperty("java.ext.dirs");
  38. for (String path : property.split(";")) {
  39. System.out.println(path);
  40. }
  41. System.out.println(Thread.currentThread().getContextClassLoader());
  42. }
  43. }

获取ClassLoader的方法:

  • clazz.getClassLoader():即Object.class.getClassLoader()或者Class.forName(String arg).getClassLoader()
  • Thread.currentThread().getContextClassLoader()
  • ClassLoader.getSystemClassLoader():系统类加载器

 

 

 

 

原文链接:https://blog.csdn.net/qq_25805331/article/details/111537865



所属网站分类: 技术文章 > 博客

作者:天使之恋

链接:http://www.javaheidong.com/blog/article/38224/1a518a05f691a1e9700a/

来源:java黑洞网

任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任

10 0
收藏该文
已收藏

评论内容:(最多支持255个字符)