JAVA一个简单自定义类加载器

一、ClassLoader加载类的顺序

 *  1.调用 findLoadedClass(String) 来检查是否已经加载类。

 *  2.在父类加载器上调用 loadClass 方法。如果父类加载器为 null,则使用虚拟机的内置类加载器。

  *  3.调用 findClass(String) 方法查找类。 *

二、实现自己的类加载器 * 1.获取类的class文件的字节数组 * 2.将字节数组转换为Class类的实例 *  *  */

以下是自定交代码

package com.myloader;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class MyClassLoader extends ClassLoader {

	// 类存放的路径
	private String path = "E:/";

	public MyClassLoader() {
	};

	@Override
	protected Class<?> findClass(String name) throws ClassNotFoundException {
		byte[] data = loadClassData(name);
		return this.defineClass(name, data, 0, data.length);
	}

	// public Class<?> loadClass(String name) throws ClassNotFoundException {
	// try {
	// String fileName = name.substring(name.lastIndexOf(".") + 1)
	// + ".class";
	// InputStream is = getClass().getResourceAsStream(fileName);
	// if (is == null)
	// return super.loadClass(name);
	// byte[] b = new byte[is.available()];
	// is.read(b);
	// return defineClass(name, b, 0, b.length);
	// } catch (IOException e) {
	// e.printStackTrace();
	// }
	// return super.loadClass(name);
	// }

	public byte[] loadClassData(String name) {
		try {
			name = name.replace(".", "//");
			File testClassFile = new File(path + name + ".class");
			System.out.println(testClassFile.getAbsolutePath());
			FileInputStream is = new FileInputStream(testClassFile);
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			int b = 0;
			while ((b = is.read()) != -1) {
				baos.write(b);
			}
			baos.flush();
			is.close();
			return baos.toByteArray();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	public static void main(String[] args) throws ClassNotFoundException,
			InstantiationException, IllegalAccessException, Exception {
		MyClassLoader cl = new MyClassLoader();
		Object obj = cl.loadClass("com.myloader.Test").newInstance();
		System.out.println(obj.getClass());
//		Thread.currentThread().setContextClassLoader(cl);
		Method method = obj.getClass().getMethod("say", null);
		method.invoke(obj, null);
		
		// Thread t = new Thread(){
		// @Override
		// public void run() {
		// Thread.currentThread().setContextClassLoader(cl);
		// Test t = new Test();
		// ClassLoader c1 = t.getClass().getClassLoader();
		// System.out.println(c1);
		// super.run();
		// }
		// };
		// t.start();
	}
}

Test类代码如下

package com.myloader;

public class Test {
	public void say() {
		System.out.println("hello world!");
		Test t = new Test();
		ClassLoader cl = t.getClass().getClassLoader();
		System.out.println(cl);
	}

}

写好后直接用ecliplse运行,

效果如下:

class com.myloader.Test
hello world!
sun.misc.Launcher$AppClassLoader@192d342

移动ecliplse工程下的class 文件,

需要把把包结构和类一起移动,我这儿是E盘:

移动后,工程的下Test.class文件就不见,E盘有一份

目录结构:E:\com\myloader\Test.class

 运行后效果如下:

E:\com\myloader\Test.class
class com.myloader.Test
hello world!
com.myloader.MyClassLoader@1bc4459

比较结果:由于AppClassLoader现在没有找到,就调用了我findClass 去E盘目录去找,找到看看现在Test t =  new test() 中实现的ClassLoader为

com.myloader.MyClassLoader@1bc4459 ,这个是我自定义的类加载器,可以看出如果如果想到加载我们自已写的就可以这样干,其实这就是一种简单的插件加载方式,

我们只需要写一个插件的加载器就可以了。

另外线程上下文类加载器 ,setContextClassLoader()这个方法可以设计类加载,会破坏双亲委派模型。这个设计后,我们在该线程任意一个地方加载我们需要的类。主要体现在SPI这些类上,列如,JDNI,JDBC,JXAB  hotswap 。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值