文档章节

JAVA ClassLoader加载机制简单分析

 风过后
发布于 2017/07/27 18:42
字数 1660
阅读 47
收藏 1

【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>>

1、什么是ClassLoader:

        我们称其为类加载器,我们的java类编译之后成为.class的文件,ClassLoader将.class文件加载进入内存然后执行相关的代码。

2、Java中的ClassLoader:

Java为我们提供了三个ClassLoader:AppClassLoader、ExtClassLoader、BootstrapClassLoader。下面我们来看他们之间的关系。

此图是我在网上找的最下面的CustomClassLoader是说我们自定义的ClassLoader这里不去管它。下面是本人关于ClassLoader的试验代码:

/**
 * 分别打印BootstrapClassLoader ExtClassLoader AppClassLoader的加载路径
 * Created by zcg on 2017/7/27.
 */
public class ClassLoaderTest {
    public static void main(String[] args){
        //获取main的类加载器
        ClassLoader classLoader = ClassLoaderTest.class.getClassLoader();
        System.out.println("main classLoader"+classLoader.toString());

        URL[] murls = ((URLClassLoader)classLoader).getURLs();
        printUrl(murls);

        System.out.println();

        //通过getParent方法获取 parent Classloader
        ClassLoader parentLoader = classLoader.getParent();
        System.out.println("parent classLoader"+parentLoader.toString());

        URL[] murlsExt = ((URLClassLoader)parentLoader).getURLs();
        printUrl(murlsExt);

        /**用反射得到其实也可以直接这样:
         *  Launcher launcher = new Launcher();
            URLClassPath urlClassPath = launcher.getBootstrapClassPath();
            System.out.println();
            printUrl(urlClassPath.getURLs());
         和下面代码等价
        打印BootstarpClassLoader加载路径 (因为是C++实现的)*/
        try {
            Class launcherClass = Class.forName("sun.misc.Launcher");
            Method method = launcherClass.getDeclaredMethod("getBootstrapClassPath", null);
            if(method != null){
                method.setAccessible(true);
                Object object = method.invoke(null, null);
                if(object != null){
                    Method methodGetUrls = object.getClass().getDeclaredMethod("getURLs", null);
                    if(methodGetUrls  != null){
                        methodGetUrls.setAccessible(true);
                        URL[] murlBoot = (URL[]) methodGetUrls.invoke(object, null);
                        printUrl(murlBoot);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public static void printUrl(URL[] urls){
        for(URL url : urls){
            System.out.println(url);
        }
    }

    从运行结果可知:MainClass的ClassLoader是AppClassLoader,APPClassLoader的getParent字段返回的是ExtClassLoader,ExtClassLoader的getParent则是空。因为BootstrapClassLoader是C++实现的,所以此处通过sun.misc.Launcher此类来获得BootstrapClassLoader。值得注意的是APPClassLoader、ExtClassLoader都是sun.misc.Launcher的子类。

    从测试类的运行结果我们可以论证上图的ClassLoader的加载路径。AppClassLoader ClassPath所指定的目录,ExtClassLoader jre/lib/ext/*,BootstrapClassLoader jre/rt.jar

/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/bin/java -Didea.launcher.port=7534 "-Didea.launcher.bin.path=/Applications/IntelliJ IDEA 15.app/Contents/bin" -Dfile.encoding=UTF-8 -classpath "/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre/lib/charsets.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre/lib/deploy.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre/lib/ext/cldrdata.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre/lib/ext/dnsns.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre/lib/ext/jaccess.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre/lib/ext/jfxrt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre/lib/ext/localedata.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre/lib/ext/nashorn.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre/lib/ext/sunec.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre/lib/ext/sunjce_provider.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre/lib/ext/sunpkcs11.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre/lib/ext/zipfs.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre/lib/javaws.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre/lib/jce.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre/lib/jfr.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre/lib/jfxswt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre/lib/jsse.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre/lib/management-agent.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre/lib/plugin.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre/lib/resources.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre/lib/rt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/lib/ant-javafx.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/lib/dt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/lib/javafx-mx.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/lib/jconsole.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/lib/packager.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/lib/sa-jdi.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/lib/tools.jar:/Users/zcg/IdeaProjects/TestJava/out/production/TestJava:/Applications/IntelliJ IDEA 15.app/Contents/lib/idea_rt.jar" com.intellij.rt.execution.application.AppMain ClassLoaderTest
main classLoadersun.misc.Launcher$AppClassLoader@4b67cf4d
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre/lib/charsets.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre/lib/deploy.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre/lib/ext/cldrdata.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre/lib/ext/dnsns.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre/lib/ext/jaccess.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre/lib/ext/jfxrt.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre/lib/ext/localedata.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre/lib/ext/nashorn.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre/lib/ext/sunec.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre/lib/ext/sunjce_provider.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre/lib/ext/sunpkcs11.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre/lib/ext/zipfs.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre/lib/javaws.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre/lib/jce.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre/lib/jfr.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre/lib/jfxswt.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre/lib/jsse.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre/lib/management-agent.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre/lib/plugin.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre/lib/resources.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre/lib/rt.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/lib/ant-javafx.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/lib/dt.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/lib/javafx-mx.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/lib/jconsole.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/lib/packager.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/lib/sa-jdi.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/lib/tools.jar
file:/Users/zcg/IdeaProjects/TestJava/out/production/TestJava/
file:/Applications/IntelliJ%20IDEA%2015.app/Contents/lib/idea_rt.jar

parent classLoadersun.misc.Launcher$ExtClassLoader@60e53b93
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre/lib/ext/cldrdata.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre/lib/ext/dnsns.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre/lib/ext/jaccess.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre/lib/ext/jfxrt.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre/lib/ext/localedata.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre/lib/ext/nashorn.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre/lib/ext/sunec.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre/lib/ext/sunjce_provider.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre/lib/ext/sunpkcs11.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre/lib/ext/zipfs.jar
file:/System/Library/Java/Extensions/MRJToolkit.jar

BootstrapClassLoader
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre/lib/resources.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre/lib/rt.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre/lib/sunrsasign.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre/lib/jsse.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre/lib/jce.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre/lib/charsets.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre/lib/jfr.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre/classes

Process finished with exit code 0

3、ClassLoader的父委托机制

protected Class<?> loadClass(String name, boolean resolve)
        throws ClassNotFoundException
    {
        synchronized (getClassLoadingLock(name)) {
            // First, check if the class has already been loaded
            Class<?> c = findLoadedClass(name);
            if (c == null) {
                long t0 = System.nanoTime();
                try {
                    if (parent != null) {
                        c = parent.loadClass(name, false);
                    } else {
                        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;
        }
    }

此处是ClassLoader中的loadClass方法,java在类加载的时候会调用此方法。

                if (parent != null) {
                        c = parent.loadClass(name, false);
                    } else {
                        c = findBootstrapClassOrNull(name);
                    }

    如果parent不为空则调用parent的loadClass方法,下面我们来看加载过来:首先调用AppClassLoader的loaderClass方法,parent不为空则调用ExtClassLoader的loaderClass方法,因为BootstrapClassLoader是C++写的所以ExtClassLoader的parent方法为null所以在ExtClassLoader中会调用findBootstrapClassOrNull(name)方法。此方法交给BootstrapClass的loaderClass()方法来加载。

    BootstrapClassLoder的加载路径jre/rt.jar如果没有找到则由ExtClassLoader在jre/ext/*加载,还是没找到则由APPClassLoader在ClassPath中加载。这就是父委托加载机制,下面用一张图来表示:

 

© 著作权归作者所有

粉丝 1
博文 17
码字总数 16917
作品 0
成都
私信 提问
浅谈java classloader

本文由作者张远道授权网易云社区发布。 类加载器三杰 jvm有三类classloader,分别是bootstrap classloader,extended classloader以及system classloader。 bootstrap classloader是系统在启动...

网易云
2018/12/14
0
0
Java代码编译和执行的整个过程

Java代码编译是由Java源码编译器来完成,流程图如下所示: Java字节码的执行是由JVM执行引擎来完成,流程图如下所示: Java代码编译和执行的整个过程包含了以下三个重要的机制: Java源码编译...

xiejunbo
2016/02/11
1K
1
Java Classloader机制解析

做Java开发,对于ClassLoader的机制是必须要熟悉的基础知识,本文针对Java ClassLoader的机制做一个简要的总结。因为不同的JVM的实现不同,本文所描述的内容均只限于Hotspot Jvm. 本文将会从...

aminqiao
2014/05/09
24.3K
2
eclipse下java动态编译时com.sun.tools.javac.Main类加载问题的解决

java.lang.NoClassDefFoundError: com/sun/tools/javac/Main 最近在使用java的动态编译的时候出现的问题,主要是由于在使用类com.sun.tool.javac.Main时,总是出现NoClassDefFoundError的错误,...

Jonee_Leo
2012/06/16
242
0
Java中类加载器classloader浅析

本篇文章来简析一下 classloader 在 Java 中的应用。 前言 现在一般一个应用程序开发会包含很多很多的类, Java 程序启动时并不是一次性将所有的类全部加载到内存中进行运行的,而是先加载部...

crazyandcoder
2019/11/27
0
0

没有更多内容

加载失败,请刷新页面

加载更多

dynamic-connectivity 动态连通性问题之 quick-union 算法

quick-union 的思想是:若对象 p 的 root_id 和对象 q 的 root_id 相等,则认为 p 和 q 连通。 若要将对象 p 和对象 q 连通(已知两对象未连通),则将 p 的 root_id 的值设为 q 的 root_id ...

Phpythoner_Alei
今天
40
0
OSChina 周六乱弹 —— 实在选不出来就唱国歌

Osc乱弹歌单(2020)请戳(这里) 【今日歌曲】 @花间小酌 :#今日歌曲推荐# 分享阿冗的单曲《你的答案》。--祝大家在2020年都找到自己答案。 《你的答案》- 阿冗 手机党少年们想听歌,请使劲...

小小编辑
今天
25
1
Maven打包可执行Jar包的方法

在使用Java开发中,会使用到将工程打包成可执行的jar包的情况,那么在maven中怎么将项目中的依赖包都添加到jar中呢。在pom.xml中添加一下插件: <build><plugins><plugin><ar...

CapJes
今天
13
0
使用vue 开发地图类系统(openlayers.js)的注意。

使用vue 开发地图类系统的注意。 1、使用地图应该创建的对象 少使用 vue 的data 和计算属性(comments)存数据或是vuex。 为什么要要注意这个问题呢? 答:这个就要了解到vue的实现原理 。原理...

DY-Tao
昨天
10
0
web移动端学习:高德地图demo(一)

在高德地图开发中申请开发者资格,然后在控制台中新建应用,获得KEY; 新建模板HTML文件; <!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>地图demo</title><scri......

dxiya
昨天
10
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部