JVM类加载器

发布于:2025-02-11 ⋅ 阅读:(52) ⋅ 点赞:(0)

什么是类加载器

类加载器(ClassLoader)是Java虚拟机提供给应用程序去实现获取类和接口字节码数据的技术。
类加载器只参与加载过程中的字节码获取并加载到内存这一部分

类加载器的分类

  • 类加载器分为两类,一类是Java代码中实现的,一类是Java虚拟机底层源码实现的。
    • 加载程序运行时的基础类
    • 继承自抽象类ClassLoader
  • JDK8及之前的版本中默认的类加载器有如下几种
    • 启动类加载器Bootstrap-加载Java中最核心的类
    • 扩展类加载器Extension-允许扩展Java中比较通用的类
    • 应用程序类加载器Application- 加载应用使用的类

通过启动类加载器去加载用户jar包:

启动类加载器(BootstrapClassLoader)是由Hotspot虚拟
默认加载Java安装目录/jre/lib下的类文件,比如rt.jar,

  • 放入jre/lib下进行扩展
    不推荐,尽可能不要去更改JDK安装目录中的内容,会出现即时放进去由于文件名不匹配的问题也不会正常地被加载
  • 使用参数进行扩展
    推荐,使用-Xbootclasspath/a:jar包目录/jar包名进行扩展

扩展类加载器Extension

扩展类加载器和应用程序类加载器都是JDK中提供的、使用Java编写的类加载器。

  • 扩展类加载器(Extension Class Loader)是JDK中提供的默认加载Java安装目录/jre/lib/ext下的类文件。
  • 在这里插入图片描述
  • 通过扩展类加载器去加载用户jar包
    • 放入/jre/lib/ext下进行扩展
    • 使用参数进行扩展
      推荐,使用-Djava.ext.dirs=jar包目录进行扩展,这种方式会覆盖掉原始目录,可以用;(windows):(macos/linux)追加上原始目录

应用程序类加载器Application

加载classpath下的类文件(也会加载ext 及启动类加载器不加载的相关 跟双亲委派有关)

Arthas中类加载器相关的功能 查看类加载器加载了什么jar

  • 类加载器的加载路径可以通过classloader–c hash值查看
    可以看到扩展类加载器加载的目录在这里插入图片描述

类加载器的双亲委派机制

双亲委派机制指的是:自底向上查找是否加载过,再由顶向下进行加载。
在这里插入图片描述

双亲委派机制有什么用?

  • 1.保证类加载的安全性
  • 2.避免重复加载

打破双亲委派机制

自定义类加载器

  • 先来分析ClassLoader的原理,ClassLoader中包含了4个核心方法。
  • 双亲委派机制的核心代码就位于loadClass方法中。
  • 正确的去实现一个自定义类加载器的方式是重写findClass方法,这样不会破坏双亲委派机制在这里插入图片描述
  • 双亲委派机制核心代码阅读
//parent等于null说明父类加载器是启动类加载器,直接调用findBootstrapClassOrNull
//否则调用父类加载器的加载方法
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;
        }
    }


网站公告

今日签到

点亮在社区的每一天
去签到