classloader 简单介绍

文章摘抄至http://longdick.iteye.com/blog/442213/

 

要深入了解ClassLoader,首先就要知道ClassLoader是用来干什么的,顾名思义,它就是用来加载Class文件到JVM,以供程序使用的。我们知道,java程序可以动态加载类定义,而这个动态加载的机制就是通过ClassLoader来实现的,所以可想而知ClassLoader的重要性如何。 

 

看到这里,可能有的朋友会想到一个问题,那就是既然ClassLoader是用来加载类到JVM中的,那么ClassLoader又是如何被加载呢?难道它不是java的类? 

 

没有错,在这里确实有一个ClassLoader不是用java语言所编写的,而是JVM实现的一部分,这个ClassLoader就是bootstrap classloader(启动类加载器),这个ClassLoader在JVM运行的时候加载java核心的API以满足java程序最基本的需求,其中就包括用户定义的ClassLoader,这里所谓的用户定义是指通过java程序实现的ClassLoader,一个是ExtClassLoader,这个ClassLoader是用来加载java的扩展API的,也就是/lib/ext中的类,一个是AppClassLoader,这个ClassLoader是用来加载用户机器上CLASSPATH设置目录中的Class的,通常在没有指定ClassLoader的情况下,程序员自定义的类就由该ClassLoader进行加载。 


 

当运行一个程序的时候,JVM启动,运行bootstrap classloader,该ClassLoader加载java核心API(ExtClassLoader和AppClassLoader也在此时被加载),然后调用ExtClassLoader加载扩展API,最后AppClassLoader加载CLASSPATH目录下定义的Class,这就是一个程序最基本的加载流程

 

java应用环境中不同的class分别由不同的ClassLoader负责加载。
一个jvm中默认的classloader有Bootstrap ClassLoader、Extension ClassLoader、App ClassLoader,分别各司其职:

  • Bootstrap ClassLoader      负责加载java基础类,主要是 %JRE_HOME/lib/ 目录下的rt.jar、resources.jar、charsets.jar和class等
  • Extension ClassLoader       负责加载java扩展类,主要是 %JRE_HOME/lib/ext 目录下的jar和class
  • App ClassLoader           负责加载当前java应用的classpath中的所有类。

其中Bootstrap ClassLoader是JVM级别的,由C++撰写;Extension ClassLoader、App ClassLoader都是java类,都继承自URLClassLoader超类。
Bootstrap ClassLoader由JVM启动,然后初始化sun.misc.Launcher ,sun.misc.Launcher初始化Extension ClassLoader、App ClassLoader。

下图是ClassLoader的加载类流程图,以加载一个类的过程类示例说明整个ClassLoader的过程。

public class ClassLoaderTree {
	public static void main(String[] args) {
		ClassLoader loader = ClassLoaderTree.class.getClassLoader();
		/**
		 sun.misc.Launcher$AppClassLoader@39ab89 系统类加载器
		 sun.misc.Launcher$ExtClassLoader@2cb49d 扩展类加载器
		 */
		while(loader != null){
			System.out.println(loader.toString());
			loader = loader.getParent();
		}
	}
}

 

Bootstrap ClassLoader、Extension ClassLoader、App ClassLoader三者的关系如下:

Bootstrap ClassLoader是Extension ClassLoader的parent,Extension ClassLoader是App ClassLoader的parent。但是这并不是继承关系,只是语义上的定义,基本上,每一个ClassLoader实现,都有一个Parent ClassLoader。

 

可以通过ClassLoader的getParent方法得到当前ClassLoader的parent。Bootstrap ClassLoader比较特殊,因为它不是java class所以Extension ClassLoader的getParent方法返回的是NULL。

 

当使用ClassLoader类的loadClass()方法来加载某个类时,该方法只是加载该类,并不会执行该类的初始化。使用Class的forName()静态方法才会导致强制初始化该类。

package hb.reflect;
public class Tester{
	static{
		System.out.println("初始化块");
	}
}

 

package hb.reflect;
public class ClassLoaderTest {
	public static void main(String[] args) throws ClassNotFoundException {
		ClassLoader c1 = ClassLoader.getSystemClassLoader();
		//不会执行初始化
		c1.loadClass("hb.reflect.Tester");
		
		System.out.println("系统加载Tester类");
		//执行初始化内容
		Class.forName("hb.reflect.Tester");
		
	}

}

 打印内容:

系统加载Tester类

初始化块

 

如果将代码如下修改:

package hb.classloader;
public class ClassLoaderTest {

	public static void main(String[] args) throws ClassNotFoundException {
		
		ClassLoader c1 = ClassLoader.getSystemClassLoader();
		//不会执行初始化
		Class clazz = c1.loadClass("hb.classloader.Tester");
		//
		try {
			Tester tester = (Tester)clazz.newInstance();
			tester.print("class.newInstance() is ok");
		} catch (InstantiationException | IllegalAccessException e) {
			e.printStackTrace();
		}
		
		System.out.println("系统加载Tester类");
		//执行初始化内容
		Class.forName("hb.classloader.Tester");
		
	}

}

 打印结果:

初始化块

class.newInstance() is ok

系统加载Tester类

 
备注:因为在调用getInstance()方法实际上就是创建一个无参的构造函数,因此需要初始化Tester类,所以与上面的有点区别。
  • af8cd370-6958-3805-a5b8-a728beb6001d-thumb.jpg
  • 大小: 65.9 KB
阅读更多
想对作者说点什么? 我来说一句

一个简单ClassLoader

2014年03月22日 975B 下载

ClassLoader原理

2010年04月23日 143KB 下载

ClassLoader运行机制 自己写的

2010年11月18日 3KB 下载

java中ClassLoader

2014年03月07日 609KB 下载

classloader源码

2009年06月23日 996KB 下载

没有更多推荐了,返回首页

不良信息举报

classloader 简单介绍

最多只允许输入30个字

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭