首页 > 代码库 > 类加载器分析(JVM)

类加载器分析(JVM)

最近去了解了下关于java虚拟机中的加载机制,特地写了篇blog来记忆下。


首先我们来了解下概念,什么是类加载器?

A:加载器就是把java的字节码从硬盘中加载到内存,然后再做一些处理,这就是类加载器所做的一些工作


默认情况下:java有默认的三个类加载器,(树状结构)从上到下分别是bootStrap、ExtClassLoader、AppClassLoader三个加载器

本质上java的类加载器为一个java类,当然也有一个是特殊的,就比如说第一个加载器bootStrap是用C++写的



优先级是从上到下:可以看下代码了解下:

package zju.zsq.day01;

public class ClassLoaderTest {

	public static void main(String[] args) {
		
		System.out.println(
				ClassLoaderTest.class.getClassLoader()
				.getClass().getName());
		System.out.println(
				System.class.getClassLoader()
				);
		
		ClassLoader loader = ClassLoaderTest.class.getClassLoader();
		//看下树状结构,如果为null就代表找不到java的class文件,等于找到了bootstrap(C++实现的加载)
		while(loader != null){
			System.out.println(loader.getClass().getName());
			loader = loader.getParent();
		}
		System.out.println(loader);
		/**
		 * AppClassLoader:只从classpath指定的目录或者jar包下面加载类
		 * ExtClassLoader:JRE/lib/ext/*.jar
		 * BootStrap:专门加载JRE/lib/rt.jar
		 */
	}
}



bootStrap:

ExtClassLoader:

AppClassLoader:


说了那么多,让我们看看java虚拟机加载一个类的时候,到底派出哪个类加载器去加载呢?

一般来说当前线程的类加载器去加载线程中的第一个类, 比如说当前的

ClassLoaderTest类,他是先让appClassLoader去加载,然后,appClassLoader委托给extClassLoader加载,然后extClassLoader委托给bootStrap加载,

而bootStrap找不到加载,又扔给extClassLoader加载,extClassLoader同样加载不了,又委托给appClassLoader加载,而appClassLoader刚好可以加载,就加载完成了

当然,如果说前面的爷爷,或者爸爸可以加载就不会让树状图下面的家宅器来加载了。如果到了appClassLoader还加载不了,那么就是runtimeError(classNotFoundException)

这就是委托机制,可以方便集中管理,不会生成多分字节码(class文件)

当然比如说当前线程是ClassLoaderTest类。那么,

如果ClassLoaderTest类引用了B类,那么就用ClassLoaderTest类的加载器去加载B类。

也可以直接调用哪个类加载器来加载 如 ClassLoader.loadClass()来指定具体某个加载器来加载类


我还记得有一道面试题特别经典。

就是能不能自己重写java.lang.System

我觉得吧,应该这样回答。当然是可以,但是你写了也是白写,因为重写后,根据委托机制,最后调用的还是系统原来的

除非自己写一个类加载器,而且这个类加载器还要比较特殊,要抛开委托机制。


我觉得应该是这样答的,