Java类加载器classLoader的工作机制

类加载器就是寻找类或接口字节码文件进行解析并构造JVM内部对象表示的组件。在Java中,类转载器把一个类装入JVM中,需要经过以下步骤:

1.装载:查找和导入Class文件;

2.链接: 执行校验、准备和解析步骤,其中解析步骤是可以选择的:

a)校验: 检查载入Class文件数据的正确性;

b)准备:给类的静态变量分配存储空间;

c)解析:将符号引用变成直接引用;

3.初始化:对类的静态变量、静态代码块进行初始化工作。

类装载工作是由ClassLoader及其之类负责的,ClassLoader是一个重要的Java运行时系统组件,它负责在运行时查找和装入Class字节文件。JVM在运行时会产生三个ClassLoader:跟装载器、ExtClassLoader(扩展类装载器)和AppClassLoader(系统类装载器)。其中,跟装载器不是ClassLoader的子类,它使用C++编写,因此我们在Java中看不到它,跟装载器负责装载JRE的核心类库,如rt.jar,charsets.jar等。ExtClassLoader和AppClassLoader都是ClassLoader的子类。其中ExtClassLoader负责装载JRE扩展目录ext中的JAR类包;AppClassLoader负责装载ClassPath路径下的类包。

这三个类装载器之间存在父子层级关系,跟装载器是ExtClassLoader的父装载器,ExtClassLoader是AppClassLoader的父装载器。默认情况下,使用AppClassLoader装载应用程序的类,我们可以试验如下:

package com.uestc.test;
public class ClassLoaderTest {
	public static void main(String[] args) {
		ClassLoader	c=Thread.currentThread().getContextClassLoader();
		System.out.println(c);
		System.out.println(c.getParent());
		System.out.println(c.getParent().getParent());
	}
}

运行结果如下:

sun.misc.Launcher$AppClassLoader@1016632
sun.misc.Launcher$ExtClassLoader@dc6a77
null

从上述结果可以分析得出当前的ClassLoader是AppClassloader,父ClassLoader是ExtClassLoader,祖父ClassLoader是根类装载器,因为在Java中无法获得它的句柄,因此返回null。


ClassLoader与Class.forName的区别

classLoader中的函数loadclass用于Class文件的加载但并没有完成初始化工作,而使用Class.forName则完成了初始化工作即完成对类的静态变量、静态代码块执行初始化工作。实例如下:

需要加载的类Reflect.java如下:

package com.uestc.test;

public class Reflect {
	private int userName;
	private int password;
	static {
		System.out.println("Reflect static block");
	}
	public Reflect(){
		System.out.println("Reflect constructs");
	}
	public int getUserName() {
		return userName;
	}
	public void setUserName(int userName) {
		this.userName = userName;
	}
	public int getPassword() {
		return password;
	}
	public void setPassword(int password) {
		this.password = password;
	}
	
}



测试类Test.java如下:

package com.uestc.test;
public class Test {
	public static void main(String[] args) {
		ClassLoader classLoader=Thread.currentThread().getContextClassLoader();
		try {
			System.out.println("使用ClassLoader中的loadClass加载:");
			classLoader.loadClass("com.uestc.test.Reflect");
			System.out.println("使用Class.forName()加载:");
			Class.forName("com.uestc.test.Reflect");
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}
运行结果如下:

使用ClassLoader中的loadClass加载:
使用Class.forName()加载:
Reflect static block

从上述结果可以看出loadClass并没有进行初始化工作,而Class.forName()进行了初始化工作。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值