getClassLoader能否为null

getClassLoader能否为null前言我们Javaer都知道类想要被加载是需要一个个ClassLoader来执行的,并且类加载的方案叫双亲委派模式,说是双亲,其实就是单亲,可能我们最初的翻译人想让我们的加载器的家庭更完整吧,所以翻译成双亲。默认的类加载器包括BootstrapClassLoader、ExtClassLoader、AppClassLoader,他们都定义在在rt.jar中的sun….

大家好,又见面了,我是你们的朋友全栈君。

前言

我们Javaer都知道类想要被加载是需要一个个ClassLoader来执行的,并且类加载的方案叫双亲委派模式,说是双亲,其实就是单亲,可能我们最初的翻译人想让我们的加载器的家庭更完整吧,所以翻译成双亲。默认的类加载器包括BootstrapClassLoader、ExtClassLoader、AppClassLoader,他们都定义在在rt.jar中的sun.misc.Launcher类中,他们的”继承”关系是AppClassLoader—>ExtClassLoader—>BootstrapClassLoader,ExtClassLoader的parent获取不到BootstrapClassLoader,只能获取到一个null。

classloader

  1. bootstrap是C++编写的类加载器,主要加载%JRE_HOME/lib/目录下的jar包
  2. ExtClassLoader主要加载%JRE_HOME/lib/ext目录下的jar包
  3. AppClassLoader主要加载java环境变量CLASSPATH所指定的路径下的jar包和class文件,通过System.getProperty(“java.class.path”)获取考验获取CLASSPATH路径
  4. 用户自定义ClassLoader,加载用户自己制定的类

getClassLoader会不会为空

说了这么多,其实就是想说getClassLoader当然可能会为空,是不是此时会有个疑惑:加载器都为空了,那这个类是怎么加载的,被谁加载的?答:被BootstrapClassLoader加载的。

我们知道BootstrapClassLoader是由C++编写的,我们是用Java代码获取不到的,BootstrapClassLoader也不是ExtClassLoader的父类,而是它的父亲,这里要搞清关系,父亲和父类是两码事,父类是有继承关系,父亲是上一层的关系,所以我们在获取String、Integer、int、double、BufferedInputStream等等一系列在rt.jar包中被BootstrapClassLoader加载的类的加载器时,返回的都是null。

ExtClassLoader是怎么成为AppClassLoader的父亲的

类加载器并非是继承关系,而是父子关系,就像上面说的BootstrapClassLoader是ExtClassLoader的父亲,不是父类。关键点就在于ClassLoader的实例变量parent,这个parent指定了当前类加载器的父亲,但是翻遍了AppClassLoader的代码也没发现是在哪里把ExtClassLoader设置进去的,怎么parent就是ExtClassLoader了呢。

刚才我们说这些类加载器被定义在了Launcher类中,那么我们就去看下这个类的构造器

public Launcher() {
  Launcher.ExtClassLoader var1;
  try {
    // 获取ExtClassLoader
    var1 = Launcher.ExtClassLoader.getExtClassLoader();
  } catch (IOException var10) {
    throw new InternalError("Could not create extension class loader", var10);
  }

  try {
    // 获取AppClassLoader实例并赋值给loader,并把ExtClassLoader的实例传入到方法中,
    this.loader = Launcher.AppClassLoader.getAppClassLoader(var1);
  } catch (IOException var9) {
    throw new InternalError("Could not create application class loader", var9);
  }
  // ...
}
// 返回AppClassLoader实例
public ClassLoader getClassLoader() {
  return this.loader;
}

从Launcher的构造器我们看到关键点在AppClassLoader.getAppClassLoader(var1)这句,那我们就看这个方法是怎么写的

static class AppClassLoader extends URLClassLoader {
  public static ClassLoader getAppClassLoader(final ClassLoader var0) throws IOException {
    final String var1 = System.getProperty("java.class.path");
    final File[] var2 = var1 == null ? new File[0] : Launcher.getClassPath(var1);
    return (ClassLoader)AccessController.doPrivileged(new PrivilegedAction<Launcher.AppClassLoader>() {
      public Launcher.AppClassLoader run() {
        URL[] var1x = var1 == null ? new URL[0] : Launcher.pathToURLs(var2);
        // 关键看这一句,调用了AppClassLoader的构造器,并把ExtClassLoader实例传了进去,那就跳到构造器去看
        return new Launcher.AppClassLoader(var1x, var0);
      }
    });
  }

  // 构造器
  AppClassLoader(URL[] var1, ClassLoader var2) {
    // 调用了父类的构造器,他的父类是哪个?从定义上看应该是URLClassLoader没跑了
    super(var1, var2, Launcher.factory);
    this.ucp.initLookupCache(this);
  }
}

其实再往里的代码就不用在这闲扯了,里面就是不断的将var2往上传递,直到ClassLoader这个类的构造器中,在ClassLoader中完成的设置。

那为什么ExtClassLoader没通过这种形式将BootstrapClassLoader设置给parent呢?

是不是傻,上面刚说了BootstrapClassLoader是C++写的,Java代码不能直观的获取。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/141668.html原文链接:https://javaforall.net

(0)
上一篇 2022年5月9日 下午5:00
下一篇 2022年5月9日 下午5:00


相关推荐

  • GIT | GIT常见面试题

    GIT | GIT常见面试题GIT 常见面试题 1 列举工作中常用的几个 git 命令 新增文件的命令 gitaddfile 或者 gitadd 提交文件的命令 gitcommit m 或者 gitcommit a 查看工作区状况 gitstatus s 拉取合并远程分支的操作 gitfetch gitmerge 或者 gitpull 查看提交记录命令 gitreflog2 提交时发生冲突 你能解释冲突是

    2026年3月20日
    2
  • python的数组怎么用_python数组的使用

    python的数组怎么用_python数组的使用1 Python 的数组分三种类型 1 list 普通的链表 初始化后可以通过特定方法动态增加元素 定义方式 arr 元素 2 Tuple 固定的数组 一旦定义后 其元素个数是不能再改变的 定义方式 arr 元素 2 Dictionary 词典类型 即是 Hash 数组 定义方式 arr 元素 k v 2 下面具体说明这些数组的使用方法和技巧 1 list 链表数组 a

    2025年10月15日
    6
  • 精灵图在线工具「建议收藏」

    精灵图在线工具「建议收藏」生成精灵图工具网站推荐精灵图自动检测工具网站推荐

    2022年6月10日
    33
  • 20210225-1 Python错误与异常「建议收藏」

    20210225-1 Python错误与异常「建议收藏」一、什么是异常Python错误与异常什么是异常>异常是一个事件,该事件会在程序执行过程中发生,影响程序的正常执行。一般情况下,在Python无法正常处理程序时就会发生异常。异常是Pyth

    2022年7月5日
    26
  • 在Linux上使用Claude Code 并使用本地VS Code SSH远程访问的完整指南

    在Linux上使用Claude Code 并使用本地VS Code SSH远程访问的完整指南

    2026年3月15日
    2
  • SpringAOP学习–SpringAOP简介及原理

    SpringAOP学习–SpringAOP简介及原理前文对AOP做了介绍,实际项目中,一般不会直接上手手动实现aop,而是使用一些高级封装的aop实现,如SpringAOP。Spring是一个广泛应用的框架,SpringAOP则是Spring提供的一个标准易用的aop框架,依托Spring的IOC容器,提供了极强的AOP扩展增强能力,对项目开发提供了极大地便利。前文提到AOP的实现有AspectJ、JDK动态代理、CGLIB动态代理,SpringAOP不是一种新的AOP实现,其底层采用的是JDK/CGLIB动态代理。JDK动态代理回顾上一篇简单介绍了

    2022年8月11日
    8

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号