JVM学习笔记(二):类加载器

类加载器就是传说中的ClassLoader。

他所做的工作就是在类加载阶段将硬盘上的二进制文件加载到内存,转化为存储在方法区中运行时的数据结构。

并产生一个位于对中的Class对象:封装了类在方法区的数据结构,为程序员提供了访问方法区数据结构的接口。

类加载器并不需要等到某个类被“首次主动使用”时再加载它。JVM规范允许类加载器在预料某个类将要被使用时就预先加载它,如果在预先加载的过程中遇到了.class文件缺失或存在错误,类加载器必须在程序首次主动使用该类时才报告错误(LinkageError错误)。如果这个类一直没有被程序主动使用,那么类加载器就不会报告错误


下面来说说ClassLoader具体的一些细节。

ClassLoader分类:

首先是JVM自带的集中ClassLoader

  1. 根类加载器(Bootstrap):这个加载器没有父类加载器。他负责加载JVM的一些核心类库,如:java.lang.*等待。他是从系统属性sun.boot.class.path所指定的目录中加载类库。他不是java.lang.ClassLoader的子类,他是有c++代码实现的,并嵌入到JVM当中,当JVM启动的时候,也随之启动。下面是些输出结果
    <span style="font-size:18px;">System.out.println(System.getProperty("sun.boot.class.path"));</span>
    输出结果:C:\Program Files\Java\jre7\lib\resources.jar;                                                                                                           C:\Program Files\Java\jre7\lib\rt.jar;                                                                                                             C:\Program Files\Java\jre7\lib\jsse.jar;                                                                                                        C:\Program Files\Java\jre7\lib\jce.jar;                                                                                                                C:\Program Files\Java\jre7\lib\charsets.jar;                                                                                                  C:\Program Files\Java\jre7\lib\jfr.jar
  2. 扩展类加载器(Extension):他是根类加载器的子类,从java.ext.dirs系统属性所指定的目录中加载类库,或者从jdk的安装目录的jre\lib\ext子目录下加载类库。他由纯java代码编写,是java.lang.ClassLoader的子类。
  3. 应用类加载器(App):负责加载classpath下的jar和class文件。由纯java代码编写,是java.lang.ClassLoader的子类。

然后我们可以自己定义ClassLoader
我们可以通过继承java.lang.ClassLoader来实现自己的ClassLoader


ClassLoader实现原理:父类委托机制
从JDK1.2开始,为了更好地保证java平台的安全性,引入父类委托机制。
规定,除了根类加载器意外,所有的加载器都要有,且只有一个父类加载器。当Java程序请求loaderOne来加载某个类的时候,loaderOne则将委托他的父加载器来加载,如果父加载器仍有父加载器,则继续向上委托,直到根类加载器。如果根类加载器加载不了,则返回给拓展类加载器,拓展类加载器仍加载不了,在返回给拓展类加载器,拓展类加载器仍加载不了,则返回给loaderOne。若loaderOne仍加载不了,则抛出ClassNotFoundException。
需要注意的是这里的父子加载器并非一定是继承关系,也可能是聚合。


父类委托机制的好处:
这种机制主要还是保证了java程序的安全。比如我们java.lang.*(如java.lang.String)中很多类是由根类加载器在JVM启动的时候就已经加载。如果我手动定义一个类也叫java.lang.String,手动调用其他非根类加载器加载,则会产生很多的问题。有了这种委托机制,可以避免这一问题。
验证一下:
<span style="font-size:18px;">ClassLoader loader = Test.class.getClassLoader();
		while(loader!=null){
			System.out.println(loader);
			loader = loader.getParent();
		}
		System.out.println(loader);</span>

输出结果为
sun.misc.Launcher$AppClassLoader@1f66cff
sun.misc.Launcher$ExtClassLoader@16de49c
null
这里要注意的是,打印根类加载器的时候会打印出null.

下面来定义一个自己的ClassLoader
首先我们要继承java.lang.ClassLoader,并要重写findClass方法。下面是代码

<span style="font-size:18px;">import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;

public class MyClassLoader extends ClassLoader
{ 
	
	private static final String path = "D:\\2015.1.21\\Other\\bin"; 
	
	
	public MyClassLoader(String name)
	{
		super(); 
		
	}
	
	
	@Override
	public Class<?> findClass(String name) throws ClassNotFoundException
	{
		byte[] data = this.loadClassData(name);
		
		return this.defineClass(name, data, 0, data.length);
	}
	
	private byte[] loadClassData(String name)
	{
		InputStream is = null;
		byte[] data = null;
		ByteArrayOutputStream baos = null;
		
		try
		{
			is = new FileInputStream(new File(path + name + ".class"));
			
			baos = new ByteArrayOutputStream();
			
			int ch = 0;
			
			while(-1 != (ch = is.read()))
			{
				baos.write(ch);
			}
			
			data = baos.toByteArray();
		}
		catch(Exception ex)
		{
			ex.printStackTrace();
		}
		finally
		{
			try
			{
				is.close();
				baos.close();
			}
			catch(Exception ex)
			{
				ex.printStackTrace();
			}
		}
		
		return data;
	}
	
	public static void main(String[] args) throws Exception
	{
		MyClassLoader loader1 = new MyClassLoader("loader1");
		Class clazz = loader1.loadClass("Test");
		Object object = clazz.newInstance(); 
		Test test = (Test)object;
		
		System.out.println(test.a);
	
		
	}	
	
	
}</span>

下面是Test类
<span style="font-size:18px;">public class Test {

	public static int a = 9;
	
}
</span>

输出结果为9

至此,关于ClassLoader的阐述到此结束。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值