ClassLoader类加载机制

       

                                             ExclassLoader                     

 

                                      AppClassLoader

 

 上图类关系出自sun.misc.Launcher类,可以看出ExclassLoader与 AppClassLoader都继承与URLClassLoader,而非继承Bootstrap ClassLoader

public class MyAppClassLoader {

    private static class Test {
        Test() {
            System.out.println("Hello World!");
        }
    }

    Launcher launcher = new Launcher();


    public static void main(String[] args) throws ClassNotFoundException {
        ClassLoader classLoader = MyAppClassLoader.class.getClassLoader();
        System.out.println(classLoader);
        System.out.println(classLoader.getParent());
        System.out.println(classLoader.getParent().getParent());
    }
}
"C:\Program Files\Java\jdk1.7.0_80\bin\java" "-javaagent:D:\idea\IntelliJ IDEA 2017.1.4\lib\idea_rt.jar=61577:D:\idea\IntelliJ IDEA 2017.1.4\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.7.0_80\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\jce.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\jfxrt.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\resources.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\rt.jar;D:\ideaprojects\NewCoderTest\out\production\NewCoderTest" MyAppClassLoader
sun.misc.Launcher$AppClassLoader@7b7035c6
sun.misc.Launcher$ExtClassLoader@3da997a
null

Process finished with exit code 0

 ExclassLoader与 AppClassLoader都继承与URLClassLoade,而URLClassLoade实现抽象类ClassLoader。

 

分析Launcher源码

Launcher.class

public Launcher() {
        Launcher.ExtClassLoader var1;
        try {
//先创建ExtClassLoader var1 = Launcher.ExtClassLoader.getExtClassLoader(); } catch (IOException var10) { throw new InternalError("Could not create extension class loader"); } try {
//由ExtClassLoader再去创建它的子类加载器,再讲将该类加载器置为Launcher的默认类加载器 this.loader = Launcher.AppClassLoader.getAppClassLoader(var1); } catch (IOException var9) { throw new InternalError("Could not create application class loader"); } Thread.currentThread().setContextClassLoader(this.loader); String var2 = System.getProperty("java.security.manager"); if(var2 != null) { SecurityManager var3 = null; if(!"".equals(var2) && !"default".equals(var2)) { try { var3 = (SecurityManager)this.loader.loadClass(var2).newInstance(); } catch (IllegalAccessException var5) { ; } catch (InstantiationException var6) { ; } catch (ClassNotFoundException var7) { ; } catch (ClassCastException var8) { ; } } else { var3 = new SecurityManager(); } if(var3 == null) { throw new InternalError("Could not create SecurityManager: " + var2); } System.setSecurityManager(var3); } }

ClassLoader.class


private static synchronized void initSystemClassLoader() { if (!sclSet) { if (scl != null) throw new IllegalStateException("recursive invocation"); sun.misc.Launcher l = sun.misc.Launcher.getLauncher(); if (l != null) { Throwable oops = null; scl = l.getClassLoader(); try { scl = AccessController.doPrivileged( new SystemClassLoaderAction(scl)); } catch (PrivilegedActionException pae) { oops = pae.getCause(); if (oops instanceof InvocationTargetException) { oops = oops.getCause(); } } if (oops != null) { if (oops instanceof Error) { throw (Error) oops; } else { // wrap the exception throw new Error(oops); } } } sclSet = true; } }



 

追踪到最后由该类进行调用 (看注释可以得出,作为默认加载器被调用)
@CallerSensitive
public static ClassLoader getSystemClassLoader() {
    initSystemClassLoader();
    if (scl == null) {
        return null;
    }
    SecurityManager sm = System.getSecurityManager();
    if (sm != null) {
        checkClassLoaderPermission(scl, Reflection.getCallerClass());
    }
    return scl;
}

  

看ClassLoader.class中的loadClass方法,探究类加载原理

    protected Class<?> loadClass(String name, boolean resolve)
        throws ClassNotFoundException
    {
//getClassLoadingLock方法,通过类名获取 synchronized (getClassLoadingLock(name)) { // 检查该类是否已经被加载过 Class c = findLoadedClass(name); if (c == null) {
//计时,输出纳秒级别时间 long t0 = System.nanoTime(); try {
//由此可见BootstrapClassLoader并不是ExtClassLoader加载器的父加载器,仅仅只是在通过父加载优先行不通的情况下,才会去找BootstrapClassLoader if (parent != null) {
//先查找父类加载器,false表示 c = parent.loadClass(name, false); } else {
//查找BootstrapClass,找不到返回null c = findBootstrapClassOrNull(name); } } catch (ClassNotFoundException e) { // ClassNotFoundException thrown if class not found // from the non-null parent class loader } if (c == null) { // If still not found, then invoke findClass in order // to find the class. long t1 = System.nanoTime();
//如果都没找到通过本加载器加载 c = findClass(name); // this is the defining class loader; record the stats sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0); sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1); sun.misc.PerfCounter.getFindClasses().increment(); } } if (resolve) { resolveClass(c); } return c; } }

 

private final ConcurrentHashMap<String, Object> parallelLockMap;
通过类名,如果paralleLockMap这个ConcurrentHashMap为空,这返回ClassLoader,否则通过putIfAbsent源码可以看到,该方法如果一个HashEntry中能够找到该key对应value值则返回该value,
如果找不到,则返回null,则返回Object
protected Object getClassLoadingLock(String className) {
            Object lock = this;
            if (parallelLockMap != null) {
            Object newLock = new Object();
            //通过putIfAbsent源码可以看到,该方法如果一个HashEntry中能够找到该key对应value值则返回该value,如果不能找到,则返回null,下面会分析ConcurrentHashMap中的该源码
            lock = parallelLockMap.putIfAbsent(className, newLock);
            if (lock == null) {
                lock = newLock;
            }
        }
        return lock;
    }

  

protected final Class<?> findLoadedClass(String name) {
        if (!checkName(name))
            return null;
        return findLoadedClass0(name);
    }
 //native关键字说明其修饰的方法是一个原生态方法,方法对应的实现不是在当前文件,而是在用其他语言(如C和C++)实现的文件中。
private native final Class findLoadedClass0(String name);

  

总结:由上的代码分析可以分析出loadClass加载类的过程,以及对BootstrapClassLoader的误解。

转载于:https://www.cnblogs.com/boycelee/p/7686956.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值