深入OpenJDK源码全面理解Java类加载器(上 -- JVM源码篇)

本文从JVM源码角度探讨类加载器,涵盖Java层面的类加载器实现,如BootStrapClassLoader、AppClassLoader和ExtClassLoader的加载过程。详细解析JVM启动流程,包括JLI_Launch函数、LoadJavaVM函数等,以及C++层面的类加载器初始化。重点关注BootStrapClassLoader的加载路径设置和类加载逻辑。
摘要由CSDN通过智能技术生成



前言

  关于JVM类加载的基础理论知识,请参照《深入理解Java虚拟机》读书笔记(六)–虚拟机类加载机制(上)《深入理解Java虚拟机》读书笔记(六)–虚拟机类加载机制(下)

一、从JVM源码看类加载器

  注:使用的是openjdk8

1.1 Java层面的类加载器

  我们都知道在Java类加载中,除了BootStrap加载器,App和Ext加载器都是Java实现的,具体实现在sun.misc.Launcher中:

public class Launcher{
   
    private static Launcher launcher = new Launcher();
    private static String bootClassPath = System.getProperty("sun.boot.class.path");
    ......
    public Launcher() {
   
        Launcher.ExtClassLoader var1;
        try {
   
            //没有显示设置父类加载器,为BootStrapClassLoader
            var1 = Launcher.ExtClassLoader.getExtClassLoader();
        } catch (IOException var10) {
   
            throw new InternalError("Could not create extension class loader", var10);
        }

        try {
   
            //设置ExtClassLoader为父类加载器
            this.loader = Launcher.AppClassLoader.getAppClassLoader(var1);
        } catch (IOException var9) {
   
            throw new InternalError("Could not create application class loader", var9);
        }
        //设置TCCL
        Thread.currentThread().setContextClassLoader(this.loader);
        ......
    }
    ......
}

  在Launcher类中,有一个静态私有成员变量launcher的赋值,调用本例的构造方法生成一个Launcher实例。因为launcher是一个类级别属性,所以这个操作会被收敛到类构造器<clinit>()方法,在该类被加载的初始化阶段被执行。

  在Launcher的构造方法中,分别初始化了Launcher.ExtClassLoader和Launcher.AppClassLoader加载器,将Launcher.loader属性(ClassLoader.getSystemClassLoader方法返回的就是这个属性)设置为了AppClassLoader,并且将TCCL设置为了AppClassLoader。ExtClassLoader和AppClassLoader初始化如下:

		//ExtClassLoader
		static class ExtClassLoader extends URLClassLoader {
   
        private static volatile Launcher.ExtClassLoader instance;

        public static Launcher.ExtClassLoader getExtClassLoader() throws IOException {
   
            if (instance == null) {
   
                Class var0 = Launcher.ExtClassLoader.class;
                synchronized(Launcher.ExtClassLoader.class) {
   
                    if (instance == null) {
   
                        instance = createExtClassLoader();
                    }
                }
            }

            return instance;
        }
}

		//AppClassLoader
		static class AppClassLoader extends URLClassLoader {
   
        final URLClassPath ucp = SharedSecrets.getJavaNetAccess().getURLClassPath(this);

        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);
                    return new Launcher.AppClassLoader(var1x, var0);
                }
            });
        }
}

  从初始化方法就可以看出,ExtClassLoader没有显示设置父加载器,所以其父类加载器是BootStrap,AppClassLoader设置ExtClassLoader为自己的父加载器。

注:加载器的父子关系不是继承上的父子关系,而是通过成员变量引用,以组合的方式实现的父子关系

1.2 JVM是如何启动的

  程序的主要入口点在main.c,代码中有大量的条件编译,我们直接看JLI_Launch函数:

return JLI_Launch(margc, margv,
                   sizeof(const_jargs) / sizeof(char *), const_jargs,
                   sizeof(const_appclasspath) / sizeof(char *), const_appclasspath,
                   FULL_VERSION,
                   DOT_VERSION,
                   (const_progname != NULL) ? const_progname : *margv,
                   (
评论 29
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值