classloader 简单介绍

系统 1384 0

文章摘抄至 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();
		}
	}
}
    

  classloader 简单介绍

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类,所以与上面的有点区别。

classloader 简单介绍


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论