ClassLoader学习笔记

本文介绍了Java中的基本类加载器,包括BootStrapClassLoader、ExtClassLoader和AppClassLoader,并详细阐述了类加载过程中的委托模式,同时提供了自定义ClassLoader的示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.   一些基本的 ClassLoader

 

Java 中基本的 ClassLoader3 个: BootStrapClassLoaderExtClassLoaderAppClassLoader

  • BootStrapClassLoader: 用于加载 <JAVA_HOME>/lib 下的类。
  • ExtClassLoader: 用于加载 <JAVA_HOME>/lib/ext 下的类。
  • AppClassLoader: 用于加载当前应用程序中用到的类。

应用程序启动后,先由 BootStrapClassLoader 加载 <JAVA_HOME>/lib 下基本的 jar ,然后由 ExtClassLoader 加载 <JAVA_HOME>/lib/ext 下的 jar ,最后由 AppClassLoader 加载 CLASSPATH 目录下定义的类。

 

2.   类的加载 / 查找过程 使用 parent 委托模式

当需要加载一个新类型 A 的时候:

  • 当前 ClassLoader 查找 A 是否已加载,如果已加载则直接返回。
  • 如果 ClassLoaderparent 不为空,则使用 parent 去加载 / 查找该类型。
  • 如果 parent 为空或 parent 加载失败,则使用 BootStrapClassLoader 去查找该类型是否已加载。
  • 如果仍然加载不成功,才使用自己去加载该类。
  • 如果还不成功,则抛出 ClassNotFoundException

使用 parent 委托模式的好处是:可以避免重复加载;可以保证核心类型(如 java.lang.String )不被用户定义覆盖。

 

3.   编写自己的 ClassLoader

  • 直接继承抽象类 ClassLoader
  • 覆盖方法 protected Class<?> findClass(String name) throws ClassNotFoundException ,一般的流程为:从资源中读取类定义到字节数组中,然后调用父类中的方法 defineClass() 来从字节数组获取 Class 对象,最后直接返回 Class 对象。
    public class MyClassLoader extends ClassLoader {
    
      protected Class<?> findClass(String name) throws ClassNotFoundException {
    	byte[] bytes = this.loadClassBytes(name);
    	Class<?> c = super.defineClass(name, bytes, 0, bytes.length);
    	if (c == null)
    		throw new ClassNotFoundException("class definition is null");
    	return c;
      }
    
      private byte[] loadClassBytes(String name) {
         ... ... ... ...
      }
    
    } 

4.  一点体会

不同的 ClassLoader 如果没有 parent-child 关系,则它们的 context 是相互独立的。同一个类在不同的 ClassLoader 中被看成是不同的且毫无关系的两个类型。

例如,执行下面的代码段,会发现输出均为false。

public void testLoadClassWithDifferentClassLoader() throws Exception {
	URL url = new URL("file:d:/temp/");
	URLClassLoader cl1 = new URLClassLoader(new URL[] { url });
	URLClassLoader cl2 = new URLClassLoader(new URL[] { url });
	Class<?> c1 = cl1.loadClass("Sample1");
	Class<?> c2 = cl2.loadClass("Sample1");
	System.out.println("c1==c2? " + (c1 == c2));
	System.out.println("c1.equals(c2)? " + c1.equals(c2));
}
 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值