深入分析ClassLoader工作机制

ClassLoader 较为深入分析。

from <深入分析Java Web>


加载CLASS到JVM中,审查每个类应该由谁加载,父优先的等级加载机制。


加载机制

ClassLoader类结构分析

ClassLoader抽象类,有很多子类,一般在实现自己的ClassLoader时候,一般都会继承URLClassLoader这个子类,因为这个类已经实现了大部分的工作,就像Servlet通过会直接HttpServlet一样。

打开源码:

几个重要的方法

  • protected final Class

等级加载机制


一层一层判断是否应该由本层ClassLoader加载,并通过在哪一层加载确定类的加载级别。

Bootstrap ClassLoader :主要加载JVM自身工作需要的类,这个ClassLoader完全由JVM自己控制的。不准守普通的加载规则,没有父类和子类。

sun.misc.Launcher java程序的入口就是sun.misc.Launcher,jdk的扩展类加载器ExtClassLoader和系统类加载器AppClassLoader都是Launcher的内部类。Launcher初始化extension classloader,system classloader,并将system classloader设置成为context classloader,但是仅仅返回system classloader给JVM。下列代码是Launcher构建的过程。

public Launcher() {

        Launcher.ExtClassLoader var1;

        ...

            var1 = Launcher.ExtClassLoader.getExtClassLoader();

        ...

            this.loader = Launcher.AppClassLoader.getAppClassLoader(var1);

....

}
类图:

  可以看到APPClassLoader和ExtClassLoader都继承自URLClassLoader,在构建Launcher过程中,先创建ExtClassLoader,然后根据ExtClassLoader作为父加载器创建APPClassLoader。然后使用Launcher的getLauncher方法得到的就是APPClassLoader。如果在Java应用中没有其他的ClassLoader,则除了”java.ext.dirs”目录下的类由ExtClassLoader加载的外,其他的都是由APPClassLoader。看一下源码。

ExtClassLoader:

    public static Launcher.ExtClassLoader getExtClassLoader() throws IOException {

            final File[] var0 = getExtDirs();//这里



            try {

                return (Launcher.ExtClassLoader)AccessController.doPrivileged(new PrivilegedExceptionAction() {

                    public Launcher.ExtClassLoader run() throws IOException {

                        int var1 = var0.length;



                        for(int var2 = 0; var2 < var1; ++var2) {

                            MetaIndex.registerDirectory(var0[var2]);

                        }



                        return new Launcher.ExtClassLoader(var0);///这里

                    }

                });

            } catch (PrivilegedActionException var2) {

                throw (IOException)var2.getException();

            }

        }



     private static File[] getExtDirs() {

                String var0 = System.getProperty("java.ext.dirs");

    ...

    }

APPClassLoader:使用ExtClassLoader作为父类加载器

 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() {

                public Launcher.AppClassLoader run() {

                    URL[] var1x = var1 == null?new URL[0]:Launcher.pathToURLs(var2);

                    return new Launcher.AppClassLoader(var1x, var0);//这里

                }

            });

        }

这是URLClassLoader的:

 public URLClassLoader(URL[] urls, ClassLoader parent,....){}
加载Class文件到内存中的2种方式

一种是隐式加载,一种是显式加载。

  1. 隐式加载: 就是不需要在代码中调用ClassLoader来加载的类,而是通过JVM来自动加载这些需要的类到内存中的方式,比如在我们继承或引用某些类的时候,JVM分析当前类引用的类不在内存中,那么就会自动加载类到内存中。

  2. 显示加载:就是在代码中调用ClassLoader来加载一个类,比如this.getClass().getClassLoader().loadClass()或者Class.forName() 或者自定义的ClassLoader的loadClass方法。

混合的方式,就是在自定义ClassLoader时候引用其他类,就

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值