栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

JVM----类加载器

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

JVM----类加载器

JVM
  • JVM如何加载一个类
    • 首先创建类加载器
    • 类加载器如何加载类
      • 双亲委派机制
    • 是否只能使用系统指定的类加载器
    • 是否可以打破双亲委派机制

JVM如何加载一个类 首先创建类加载器

window会调用jvm.dll(dll相当于jar)创建一个由c++编写的sun.misc.Launcher类(单例模式:确保该类只有唯一一个)在初始化过程中会创建两个加载器,一个是ExtClassLoader扩展类加载器,另一个是AppClassLoader应用类加载器。

 //Launcher构造方法
 public Launcher() {
 ExtClassLoader var1;
        try {
        //扩展类加载器
            var1 = Launcher.ExtClassLoader.getExtClassLoader();
        } catch (IOException var10) {
            throw new InternalError("Could not create extension class loader", var10);
        }
        try {
        //应用类加载器
            this.loader = Launcher.AppClassLoader.getAppClassLoader(var1);
        } catch (IOException var9) {
            throw new InternalError("Could not create application class loader", var9);
        }
 //省略其他
 }

三个加载器之间的关系

ClassLoader appClassLoader = ClassLoader.getSystemClassLoader();
ClassLoader extClassloader = appClassLoader.getParent();
ClassLoader bootstrapLoader = extClassloader.getParent();
//        扩展类加载器的父类是引导类加载器,引导类加载器在java中显示不出为NULL
System.out.println("the bootstrapLoader : " + bootstrapLoader);
//        应用类加载器的父类是扩展类加载器
System.out.println("the extClassloader : " + extClassloader);
//        应用类是由应用类加载器负责加载的
System.out.println("the appClassLoader : " + appClassLoader);
//结果
the bootstrapLoader : null
the extClassloader : sun.misc.Launcher$ExtClassLoader@4b67cf4d
the appClassLoader : sun.misc.Launcher$AppClassLoader@18b4aac2

各加载器所加载的文件位置

引导类加载器加载以下文件:
file:/C:/Program%20Files/Java/jdk1.8.0_202/jre/lib/resources.jar
file:/C:/Program%20Files/Java/jdk1.8.0_202/jre/lib/rt.jar
file:/C:/Program%20Files/Java/jdk1.8.0_202/jre/lib/sunrsasign.jar
file:/C:/Program%20Files/Java/jdk1.8.0_202/jre/lib/jsse.jar
file:/C:/Program%20Files/Java/jdk1.8.0_202/jre/lib/jce.jar
file:/C:/Program%20Files/Java/jdk1.8.0_202/jre/lib/charsets.jar
file:/C:/Program%20Files/Java/jdk1.8.0_202/jre/lib/jfr.jar
file:/C:/Program%20Files/Java/jdk1.8.0_202/jre/classes

扩展类加载以下文件:
C:Program FilesJavajdk1.8.0_202jrelibext;C:WindowsSunJavalibext

应用类加载以下我们自己的应用类:
C:Program FilesJavajdk1.8.0_202jrelibcharsets.jar;C:Program FilesJavajdk1.8.0_202jrelibdeploy.jar;C:Program FilesJavajdk1.8.0_202jrelibextaccess-bridge-64.jar;C:Program FilesJavajdk1.8.0_202jrelibextcldrdata.jar;C:Program FilesJavajdk1.8.0_202jrelibextdnsns.jar;C:Program FilesJavajdk1.8.0_202jrelibextjaccess.jar;C:Program FilesJavajdk1.8.0_202jrelibextjfxrt.jar;C:Program FilesJavajdk1.8.0_202jrelibextlocaledata.jar;C:Program FilesJavajdk1.8.0_202jrelibextnashorn.jar;C:Program FilesJavajdk1.8.0_202jrelibextsunec.jar;C:Program FilesJavajdk1.8.0_202jrelibextsunjce_provider.jar;C:Program FilesJavajdk1.8.0_202jrelibextsunmscapi.jar;C:Program FilesJavajdk1.8.0_202jrelibextsunpkcs11.jar;C:Program FilesJavajdk1.8.0_202jrelibextzipfs.jar;C:Program FilesJavajdk1.8.0_202jrelibjavaws.jar;C:Program FilesJavajdk1.8.0_202jrelibjce.jar;C:Program FilesJavajdk1.8.0_202jrelibjfr.jar;C:Program FilesJavajdk1.8.0_202jrelibjfxswt.jar;C:Program FilesJavajdk1.8.0_202jrelibjsse.jar;C:Program FilesJavajdk1.8.0_202jrelibmanagement-agent.jar;C:Program FilesJavajdk1.8.0_202jrelibplugin.jar;C:Program FilesJavajdk1.8.0_202jrelibresources.jar;C:Program FilesJavajdk1.8.0_202jrelibrt.jar;E:编程代码LearnJVMoutproductiontuling;C:Program FilesJetBrainsIntelliJ IDEA 2022.1.1libidea_rt.jar

类加载器如何加载类
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;
        }
    }
双亲委派机制

以上代码是双亲委派的具体实现,首先判断当前类是否被加载,如果当前类没有被加载,首先判断父类是否为空,如果不为空则委托父类加载该类,如果父类为空则委托引导类加载器去加载该类,如果父类和引导类加载器都没有找到该类,则自己调用findClass(name)去查找该类。
简单来说就是子类在加载一个类的时候,先让父类(存在)和引导类加载器去查找该类,如果父类和引导类都找不到这个类,则自己去找这个类。、

为什么要这么设计?
1.沙箱安全机制:防止java自己的核心类被修改,如创建一个与java核心类相同名称的类,去冒充java核心类。
2.避免类的重复加载,如果父类已经加载过了,子类就不用再加载了

是否只能使用系统指定的类加载器

不是,自定义类加载器只要继承了ClassLoader的loadClass方法并且重写findclass方法,就可以实现: 自定义类加载器

是否可以打破双亲委派机制

可以,通过重写loadclass方法不使用原本的parent.loadclass即可打破。
为什么要打破双亲委派机制呢?
例如tomcat:
1.如果一个tomcat上部署了多个应用程序,每个程序使用的同一个依赖的不同版本,可以通过该方法解决,因为如果不同版本全限定类名一致的话,那么只能加载其中一个。
2.jsp文件热加载:当jsp文件修改之后,通过卸载jsp对应的类加载器然后重新创建该类加载器,重新加载jsp文件。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1031902.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号