Java类加载机制

ClassLoader类加载器

类加载器的作用

类加载器用于加载编译生成的 *.class 文件内容(每一个类在编译之后都会生成一个.class文件)。

Java有以下几种类加载器:

Bootstrap(启动类加载器,C++实现):用于加载%JAVA_HOME%/lib目录下(或者被Xbootclasspath参数指定路径中)能被虚拟机识别的类库加载到JVM内存中,启动类加载器是由C++实现的,所以无法被Java程序直接引用。

ExtClassLoader(扩展类加载器,Java实现):用于加载%JAVA_HOME%/lib/ext目录下(或者被java.ext.dirs系统变量指定路径中的类库),他可以被Java程序调用。

AppClassLoader(应用程序类加载器):负责加载用户路径(ClassPath)上指定的类库,如果应用程序没有自定义自己的类加载器,AppClassLoader就是默认的类加载器

来看一段查看Java类加载器的代码

public class Test{
	
	public static void main(String[] args) {
		System.out.println("当前类的类加载器:" + Test.class.getClassLoader());
		System.out.println(Test.class.getClassLoader().getParent());
		System.out.println(Test.class.getClassLoader().getParent().getParent());
	}
}

运行结果如下:


可见默认的类加载器是AppClassLoader。而且只可以看见AppClassLoader和ExtClassLoader,因为Bootstrap(启动类加载器是不能被Java程序直接调用的)。


双亲委派模型:


执行类加载的时候,并不会使用当前类加载器(默认的类加载器是AppClassLoader)。而是直接查看当前类加载器的父类加载器是否能加载,如果能加载,就让父类加载器加载,这一举动保证了Java程序的运行正常。

自定义类加载器

为什么要自定义类加载器?

(1)加密:众所周知,java代码很容易被反编译,如果你需要把自己的代码进行加密,可以先将编译后的代码用某种加密算法加密,然后实现自己的类加载器,负责将这段加密后的代码还原。
(2)从非标准的来源加载代码:由于存在的三个类加载器只能加载环境指定目录下的类。但是你的部分字节码(*.class文件)是放在数据库中甚至是网络上的,就可以自己写个类加载器,从指定的来源加载类。

(3)动态创建:为了性能等等可能的理由,根据实际情况动态创建代码并执行。

自定义类加载器的代码实现:

import java.io.*;

class MyClassLoader extends ClassLoader{
	public Class<?> loadMyClass(String className) throws IOException{
		FileInputStream fis = new FileInputStream("C:\\Users\\hasee\\Desktop\\testClassLoader\\Person.class");
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		byte[] b = new byte[1024];
		int flag = 0;
		while((flag = fis.read(b)) != -1) {
			baos.write(b, 0, flag);
		}
		byte[] result = baos.toByteArray();
		baos.close();
		fis.close();
		return defineClass(className, result, 0, result.length);
	}
}

public class Test {
	public static void main(String[] args) throws InstantiationException, IllegalAccessException, IOException {
		MyClassLoader myCls = new MyClassLoader();
		Class<?> class1 = myCls.loadMyClass("Person");
		System.out.println(class1.getClassLoader());
		System.out.println(class1.getClassLoader().getParent());
		System.out.println(class1.getClassLoader().getParent().getParent());
		System.out.println(class1.getClassLoader().getParent().getParent().getParent());
		System.out.println(class1.newInstance());
	}
}

Person类:

public class Person{
	public String toString(){
		return "my class loader";
	}
}

运行结果:





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值