Java ClassLoader机制分析 -- Tomcat commloader 例说

本文详细分析了Tomcat中ClassLoader的创建过程,从Bootstrap开始,逐步讲解了如何创建commonLoader,涉及URLClassLoader的构造及其父类加载器的设置。此外,还探讨了ExtClassLoader和AppClassLoader的创建,以及类加载的步骤,包括findLoadedClass、loadClass、findClass和defineClass等关键方法的作用。通过这个过程,我们理解了Tomcat如何加载自定义路径下的资源以及自定义类加载器的重要性。
摘要由CSDN通过智能技术生成
最终整理一下Tomcat 的ClassLoader创建流程如下:

1.	入口
Bootstrap bootstrap = new Bootstrap();
bootstrap.init();
initClassLoaders();
	ClassLoader commonLoader = createClassLoader("common", null); 
createClassLoader("common", null) {
		String value = CatalinaProperties.getProperty("common.loader");
		if (value == null || “”) {
			 return commonLoader = parent. 即 null.
		} else {
			将value对应的目录和文件所在目录转成Repository的数组,并执行
			ClassLoaderFactory.createClassLoader(repositories, parent);
				将repository的jar文件(一般都是jar)转化成URL存入到数组中。执行:
				return new URLClassLoader(array);
			
		}
   }
   如果 commonLoader==null, 则 commonLoader=parent 亦为null,表示无需额外资源加载。

2.	new URLClassLoader(array) 函数
URLClassLoader(URL[] urls) 
	SecureClassLoader()
		ClassLoader() {
			this(checkCreateClassLoader(), getSystemClassLoader());
		}

这里前者就是check RuntimePermission("createClassLoader") 运行时权限
getSystemClassLoader()就是生成系统类 cloassloader. 主要调用 initSystemClassLoader(); 函数
initSystemClassLoader()
	sun.misc.Launcher l = sun.misc.Launcher.getLauncher();
	Launcher实例化的时候调用下面代码:
	new Launcher() {
		// 创建扩展类加载器,主要加载System.getProperty("java.ext.dirs")目录下相关资源
 		// 例如: $JAVA_HOME/lib/ext, $JAVA_HOME/jre/lib/ext
		ClassLoader extcl = ExtClassLoader.getExtClassLoader();

		// 创建 “java类路径”加载器,主要加载 System.getProperty("java.class.path") 目录下相关资源
		// 可以通过 ps –ef | grep java 查看 –classpath 得到。
		ClassLoader loader = AppClassLoader.getAppClassLoader(extcl);
	}

上述也进一步说明编写自己 classloader 的必要行。
启动类加载器只加载JVM启动所必需的类,为C编写,加载的如 java.*,javax.*等文件。
扩展类加载器只加载 java.ext.dirs 目录下的资源
应用类加载器只加载 java.class.path  里面,即 –classpath 对应的资源。
那么 tomcat/lib 等资源如何加载呢? 这就是 tomcat commonClassLoader 的用途了。
同理 对于具体的webapp,没有目前的加载器没有加载,需要写自己的加载器加载 web/lib, web/classes等资源。
3.	ExtClassLoader.getExtClassLoader();
URLStreamHandlerFactory factory = new Factory();

File[] dirs = getExtDirs(); // System.getProperty("java.ext.dirs");
new ExtClassLoader(dirs);
	super(getExtURLs(dirs), null, factory); // 将dir中文件转成 java.net.URL[]
	即:
	URLClassLoader(URL[] urls, ClassLoader parent, URLStreamHandlerFactory factory) {
		回到了步骤2,但是这次带了parent=null, 和 factory.
		步骤而的 super() 变成 super(parent);

		这样最终的ClassLoader如下:
		protected ClassLoader(ClassLoader parent) {
        this(checkCreateClassLoader(), parent);
}
这里直接传入 parent classloader, 就不在实例化系统类加载器了。
	}


4.	ClassLoader 具体工作
ClassLoader有多个构造函数,但最终都是通过下面的构造函数工作。

	// 父类加载器,ext的为null.
	private final ClassLoader parent;
    // 设置父classloader和初始化一些属性。
	private ClassLoader(Void unused, ClassLoader parent) {
        this.parent = parent; 
        if (ParallelLoaders.isRegistered(this.getClass())) {
            parallelLockMap = new ConcurrentHashMap<>();
            package2certs = new ConcurrentHashMap<>();
            domains =
                Collections.synchronizedSet(new HashSet<ProtectionDomain>());
            assertionLock = new Object();
        } else {
            // no finer-grained lock; lock on the classloader instance
            parallelLockMap = null;
            package2certs = new Hashtable<>();
            domains = new HashSet<>();
            assertionLock = this;
        }
    }
其实这个类里比较有用的是 loadClss(), findClass(), 以及 defineClass() 等。
通过上述,将 ExtClassLoader 对象(extcl)创建出来了
下面继续AppClassLoader的class loader创建



5.	Launcher的构造函数有 ClassLoader loader = AppClassLoader.getAppClassLoader(extcl);
public static ClassLoader getAppClassLoader(final ClassLoader extcl) throws IOException {
			// 加载资源的路径为 classpath 路径
            final String s = System.getProperty("java.class.path");
            final File[] path = (s == null) ? new File[0] :
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值