Java虚拟机类加载器

怼烎@ 2023-06-26 08:27 133阅读 0赞

类加载器

虚拟机设计团队把类加载阶段中的获取二进制字节流这个动作放到Java虚拟机外部去实现,一遍让程序自己决定如何去获取所需要的类,实现这个动作的代码块被称为“类加载器”。
同一个Class文件如果被不同的类加载器所加载,那么加载出来的两个类是不相等的,所以某个Class文件只能由一个加载器加载。
这边的相等是Class兑现的equals()方法,isInstance()方法,isAssignableFrom()方法返回的结果。

  1. import java.io.IOException;
  2. import java.io.InputStream;
  3. public class ClassLoaderTest {
  4. public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
  5. ClassLoader myLoader = new ClassLoader() {
  6. @Override
  7. public Class<?> loadClass(String name) throws ClassNotFoundException {
  8. try {
  9. String className = name.substring(name.lastIndexOf(".") + 1) + ".class";
  10. //返回读取指定资源的输入流
  11. InputStream is = getClass().getResourceAsStream(className);
  12. if (is == null) return super.loadClass(name);
  13. byte[] b = new byte[is.available()];
  14. is.read(b);
  15. //将一个byte数组转换为Class类的实例
  16. return defineClass(name, b, 0, b.length);
  17. } catch (IOException e) {
  18. throw new ClassNotFoundException(name);
  19. }
  20. }
  21. };
  22. Object object = myLoader.loadClass("ClassLoaderTest").newInstance();
  23. System.out.println(object.getClass());
  24. System.out.println(object instanceof ClassLoaderTest);
  25. }
  26. }

以上代码运行结果如下图所示:
可以看到不同加载器说加载的类结果instanceof为false。
在这里插入图片描述

双亲委派模型

下面是双亲委派模型的实现,很明显可以看出,为了防止上面的不同类加载器加载同一个class文件的问题,双亲委派模型在加载Class文件的时候先问问其父类加载器有没有加载,所以,最先开始的是:

  • 启动类加载器(Bootstrap ClassLoader)这个加载器负责将存放在JAVA_HOME\bin目录下的包,或者被-Xbootclasspath参数所指定的路径中,并且是虚拟机识别的(即使是自己的包放到这个目录下,是不会被加载的)
  • 扩展类加载器(Extension ClassLoader):这个加载器负责JAVA_HOME\bin\ext目录中的,或者被java.ext.dirs系统变量所指定的路径中的所有类库,开发者可以直接使用扩展类加载器。
  • 应用程序类加载器(Application ClassLosder):这个加载器负责加载ClassPath上所指定的类库,

先检查是否被加载过,若没有加载则调用父类加载器的loadClass()方法,若父类加载器为空则默认使用启动类加载器作为父类加载器,如果父类加载器加载失败,抛出ClassNotFoundException异常后,再调用自己的findClass()方法进行加载。

  1. protected synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
  2. //1 首先检查类是否被加载
  3. Class c = findLoadedClass(name);
  4. if (c == null) {
  5. try {
  6. if (parent != null) {
  7. //2 没有则调用父类加载器的loadClass()方法;
  8. c = parent.loadClass(name, false);
  9. } else {
  10. //3 若父类加载器为空,则默认使用启动类加载器作为父加载器;
  11. c = findBootstrapClass0(name);
  12. }
  13. } catch (ClassNotFoundException e) {
  14. //4 若父类加载失败,抛出ClassNotFoundException 异常后
  15. c = findClass(name);
  16. }
  17. }
  18. if (resolve) {
  19. //5 再调用自己的findClass() 方法。
  20. resolveClass(c);
  21. }
  22. return c;
  23. }

发表评论

表情:
评论列表 (有 0 条评论,133人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Java虚拟

    类加载器 虚拟机设计团队把类加载阶段中的获取二进制字节流这个动作放到Java虚拟机外部去实现,一遍让程序自己决定如何去获取所需要的类,实现这个动作的代码块被称为“类加载器

    相关 Java虚拟机制

    类的主动加载时机: 1、当遇到new、getstatic、putstatic、invokestatic这4条指令时,如果类没有进行初始化,则首先进行初始 化。出现这些指令的代