从0到1理解动态类加载

admin 2026-02-10 14:24:57 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 本文详细解析Java动态类加载机制,涵盖类生命周期(加载、准备、初始化、使用)、双亲委派模型(Bootstrap/Extension/System/自定义类加载器层级)及源码调试分析。重点跟踪ClassLoader.loadClass()至URLClassLoader.findClass()的完整调用链,说明如何通过重写loadClass打破双亲委派或重写findClass实现自定义加载,为理解Java安全基础与反序列化漏洞利用提供底层原理支撑。 综合评分: 78 文章分类: 代码审计,安全开发,应用安全,WEB安全,二进制安全


cover_image

从0到1理解动态类加载

小猫咪 小猫咪

梦想变成大黑客的小猫咪

2026年2月9日 16:55 北京

动态类加载是Java安全基础中的核心。

类的声明周期

简单列举一下几个阶段:

加载:加载这一步主要是通过 类加载器 完成的。类加载器有很多种,当我们想要加载一个类的时候,具体是哪个类加载器加载由 双亲委派模型 决定(不过,我们也能打破双亲委派模型)。

准备:JVM 会在该阶段对类变量(也称为静态变量,static 关键字修饰的)分配内存并初始化,对应数据类型的默认初始值,如 0、0L、null、false 等。

初始化:初始化阶段是执行初始化方法  ()方法的过程,是类加载的最后一步,这一步 JVM 才开始真正执行类中定义的 Java 程序代码(字节码)。初始化阶段,类变量将被赋值为代码期望赋的值。

使用:就是new,代码中实际进行使用这个类,创建对象

初始化执行的代码

静态参数的赋值 会调用静态代码块,初始化的时候就会调用静态代码块中

Class a=Student.class;

ClassLoader  cl=ClassLoader.getSystemClassLoader();
Class.forName("Student",false,cl);

ClassLoader  cl=ClassLoader.getSystemClassLoader();
Class<?> c=cl.loadClass("Student");

只进行加载不会进行初始化

Class.forName("Student");

ClassLoader &nbsp;cl=ClassLoader.getSystemClassLoader();
Class<?> c=Class.forName("Student",false,cl);
c.newInstance();实例化

ClassLoader &nbsp;cl=ClassLoader.getSystemClassLoader();
Class<?> c=cl.loadClass("Student");
c.newInstance();实例化

进行初始化会进行初始化调用静态代码块

类加载器

①、引导类加载器(Bootstrap ClassLoader):负责加载 JVM 基础核心类库,如 rt.jar、sun.boot.class.path 路径下的类。

②、扩展类加载器(Extension ClassLoader):负责加载 Java 扩展库中的类,例如 jre/lib/ext 目录下的类或由系统属性 java.ext.dirs 指定位置的类。

③、系统(应用)类加载器(System ClassLoader):负责加载系统类路径 java.class.path 上指定的类库,通常是你的应用类和第三方库。

④、用户自定义类加载器:Java 允许用户创建自己的类加载器,通过继承 java.lang.ClassLoader 类的方式实现。这在需要动态加载资源、实现模块化框架或者特殊的类加载策略时非常有用。

ClassLoader的加载机制(向上委托优先、向下尝试加载兜底)

双亲委派模型:如果一个类加载器收到了加载类的请求,它会先把请求委托给上层加载器去完成,上层加载器又会委托上上层加载器,一直到最顶层的类加载器;如果上层加载器无法完成类的加载工作时,当前类加载器才会尝试自己去加载这个类。

通俗理解先给自己的父类加载器,一直给到最顶端bootstrap classloader,如果被加载到了就不回往下进行传递。

并不是继承关系是逻辑上 的父类,逻辑的指向

加载的顺序如下:

应用程序类加载器 → 扩展类加载器 → 启动类加载器(失败)→ 扩展类加载器(失败)→ 应用程序类加载器

源代码分析

跟踪一下源码进行调试分析

ClassLoader &nbsp;cl=ClassLoader.getSystemClassLoader();
Class<?> c=cl.loadClass("Student");

先调用到了ClassLoader类的方法

因为AppClassLoader没有一个参数的loadClass

&nbsp;public Class<?> loadClass(String name) throws ClassNotFoundException {
&nbsp; &nbsp; &nbsp; &nbsp; return loadClass(name, false);
&nbsp; &nbsp; }

又回到AppClassLoader

public Class<?> loadClass(String name, boolean resolve)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throws ClassNotFoundException
&nbsp; &nbsp; &nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; int i = name.lastIndexOf('.');
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (i != -1) {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SecurityManager sm = System.getSecurityManager();
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (sm != null) {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sm.checkPackageAccess(name.substring(0, i));
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (ucp.knownToNotExist(name)) {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // The class of the given name is not found in the parent
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // class loader as well as its local URLClassPath.
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Check if this class has already been defined dynamically;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // if so, return the loaded class; otherwise, skip the parent
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // delegation and findClass.
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Class<?> c = findLoadedClass(name);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (c != null) {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (resolve) {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; resolveClass(c);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return c;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throw new ClassNotFoundException(name);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return (super.loadClass(name, resolve));
&nbsp; &nbsp; &nbsp; &nbsp; }

又回到父类ClassLoader中

双亲委派的流程ClassLoader类中如下

&nbsp; &nbsp; protected Class<?> loadClass(String name, boolean resolve)
&nbsp; &nbsp; &nbsp; &nbsp; throws ClassNotFoundException
&nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; synchronized (getClassLoadingLock(name)) {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // First, check if the class has already been loaded
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Class<?> c = findLoadedClass(name);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (c == null) {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; long t0 = System.nanoTime();
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; try {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (parent != null) {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; c = parent.loadClass(name, false);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; c = findBootstrapClassOrNull(name);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } catch (ClassNotFoundException e) {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // ClassNotFoundException thrown if class not found
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // from the non-null parent class loader
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (c == null) {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // If still not found, then invoke findClass in order
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // to find the class.
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; long t1 = System.nanoTime();
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; c = findClass(name);

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // this is the defining class loader; record the stats
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sun.misc.PerfCounter.getFindClasses().increment();
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (resolve) {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; resolveClass(c);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return c;
&nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; }

Class<?> c = findLoadedClass(name);
if (resolve) {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; resolveClass(c);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return c;
&nbsp; &nbsp; &nbsp; &nbsp; }

查看是否被加载,如果加载到了,直接就会被返回

如果没有被加载,执行下面的内容

if (c == null) {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; long t0 = System.nanoTime();
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; try {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (parent != null) {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; c = parent.loadClass(name, false);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; c = findBootstrapClassOrNull(name);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } catch (ClassNotFoundException e) {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // ClassNotFoundException thrown if class not found
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // from the non-null parent class loader
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (c == null) {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // If still not found, then invoke findClass in order
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // to find the class.
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; long t1 = System.nanoTime();
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; c = findClass(name);

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // this is the defining class loader; record the stats
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sun.misc.PerfCounter.getFindClasses().increment();
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }

parent不是空的就让parent.loadClass(name, false);父类进行加载

父类等于空说明在最顶层了 使用Bootstrap ClassLoader进行加载,Bootstrap ClassLoader是JVM底层的C++实现,不属于Java类加载器体系,故返回null(ExtClassLoader的 parent 是null

c = findBootstrapClassOrNull(name);

抛到顶层没有被加载就调用自己的findClass进行加载

如果想要打破双亲委派就进行重写loadclass方法,如果不进行打破就重写findclass就可以了。

当前是ExtClassLoader调用findClass

所以到了它的父类URLClassLoader

protected Class<?> findClass(final String name)
&nbsp; &nbsp; &nbsp; &nbsp; throws ClassNotFoundException
&nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; final Class<?> result;
&nbsp; &nbsp; &nbsp; &nbsp; try {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; result = AccessController.doPrivileged(
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; new PrivilegedExceptionAction<Class<?>>() {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; public Class<?> run() throws ClassNotFoundException {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; String path = name.replace('.', '/').concat(".class");
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Resource res = ucp.getResource(path, false);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (res != null) {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; try {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return defineClass(name, res);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } catch (IOException e) {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throw new ClassNotFoundException(name, e);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return null;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }, acc);
&nbsp; &nbsp; &nbsp; &nbsp; } catch (java.security.PrivilegedActionException pae) {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throw (ClassNotFoundException) pae.getException();
&nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; &nbsp; &nbsp; if (result == null) {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throw new ClassNotFoundException(name);
&nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; &nbsp; &nbsp; return result;
&nbsp; &nbsp; }

没有加载到 回退

当前是AppClassLoader

所以到了它的父类URLClassLoader

protected Class<?> findClass(final String name)
&nbsp; &nbsp; &nbsp; &nbsp; throws ClassNotFoundException
&nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; final Class<?> result;
&nbsp; &nbsp; &nbsp; &nbsp; try {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; result = AccessController.doPrivileged(
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; new PrivilegedExceptionAction<Class<?>>() {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; public Class<?> run() throws ClassNotFoundException {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; String path = name.replace('.', '/').concat(".class");
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Resource res = ucp.getResource(path, false);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (res != null) {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; try {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return defineClass(name, res);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } catch (IOException e) {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throw new ClassNotFoundException(name, e);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return null;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }, acc);
&nbsp; &nbsp; &nbsp; &nbsp; } catch (java.security.PrivilegedActionException pae) {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throw (ClassNotFoundException) pae.getException();
&nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; &nbsp; &nbsp; if (result == null) {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throw new ClassNotFoundException(name);
&nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; &nbsp; &nbsp; return result;
&nbsp; &nbsp; }

path  xxx.class

Resource res = ucp.getResource(path, false); 就是在系统类路径 java.class.path 上指定的类库,通常是你的应用类和第三方库。

找到了res不等于空

就会调用 defineClass(name, res);

private Class<?> defineClass(String name, Resource res) throws IOException {
&nbsp; &nbsp; &nbsp; &nbsp; long t0 = System.nanoTime();
&nbsp; &nbsp; &nbsp; &nbsp; int i = name.lastIndexOf('.');
&nbsp; &nbsp; &nbsp; &nbsp; URL url = res.getCodeSourceURL();
&nbsp; &nbsp; &nbsp; &nbsp; if (i != -1) {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; String pkgname = name.substring(0, i);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Check if package already loaded.
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Manifest man = res.getManifest();
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; definePackageInternal(pkgname, man, url);
&nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; &nbsp; &nbsp; // Now read the class bytes and define the class
&nbsp; &nbsp; &nbsp; &nbsp; java.nio.ByteBuffer bb = res.getByteBuffer();
&nbsp; &nbsp; &nbsp; &nbsp; if (bb != null) {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Use (direct) ByteBuffer:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CodeSigner[] signers = res.getCodeSigners();
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CodeSource cs = new CodeSource(url, signers);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sun.misc.PerfCounter.getReadClassBytesTime().addElapsedTimeFrom(t0);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return defineClass(name, bb, cs);
&nbsp; &nbsp; &nbsp; &nbsp; } else {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; byte[] b = res.getBytes();
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // must read certificates AFTER reading bytes.
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CodeSigner[] signers = res.getCodeSigners();
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CodeSource cs = new CodeSource(url, signers);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sun.misc.PerfCounter.getReadClassBytesTime().addElapsedTimeFrom(t0);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return defineClass(name, b, 0, b.length, cs);
&nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; }

SecureClassLoader类中

protected final Class<?> defineClass(String name,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;byte[] b, int off, int len,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;CodeSource cs)
&nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; return defineClass(name, b, off, len, getProtectionDomain(cs));
&nbsp; &nbsp; }

ClassLoader类中

protected final Class<?> defineClass(String name, byte[] b, int off, int len,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ProtectionDomain protectionDomain)
&nbsp; &nbsp; &nbsp; &nbsp; throws ClassFormatError
&nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; protectionDomain = preDefineClass(name, protectionDomain);
&nbsp; &nbsp; &nbsp; &nbsp; String source = defineClassSourceLocation(protectionDomain);
&nbsp; &nbsp; &nbsp; &nbsp; Class<?> c = defineClass1(name, b, off, len, protectionDomain, source);
&nbsp; &nbsp; &nbsp; &nbsp; postDefineClass(c, protectionDomain);
&nbsp; &nbsp; &nbsp; &nbsp; return c;
&nbsp; &nbsp; }
private native Class<?> defineClass1(String name, byte[] b, int off, int len,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ProtectionDomain pd, String source);

AppClassLoader 继承 URLClassLoader

ExtClassLoader同样继承 URLClassLoader

URLClassLoader 的⽗类的 SecureClassLoader

总的流程:

ClassLoader —-> SecureClassLoader —> URLClassLoader —-> APPClassLoader

loadClass() —-> findClass(重写的方法)—–》defineclass(从字节码加载类)


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:梦想变成大黑客的小猫咪 小猫咪 小猫咪《从0到1理解动态类加载》

评论:0   参与:  3