0
点赞
收藏
分享

微信扫一扫

MyLoadClass (自己写类加载器)


MyLoadClass (自己写类加载器)_加载

Api中:

通常情况下,Java 虚拟机以与平台有关的方式,从本地文件系统中加载类。例如,在 UNIX 系统中,虚拟机从 CLASSPATH

然而,有些类可能并非源自一个文件;它们可能源自其他来源(如网络),也可能是由应用程序构造的。​​defineClass​​​ 方法将一个 byte 数组转换为 Class 类的实例。这种新定义的类的实例可以使用 ​​Class.newInstance​​ 来创建。

类加载器所创建对象的方法和构造方法可以引用其他类。为了确定引用的类,Java 虚拟机将调用最初创建该类的类加载器的 ​​loadClass​​ 方法。

例如,应用程序可以创建一个网络类加载器,从服务器中下载类文件。示例代码如下所示:

ClassLoader loader = new NetworkClassLoader(host, port); Object main = loader.loadClass("Main", true).newInstance();  . . .

网络类加载器子类必须定义方法 ​​findClass​​​ 和 loadClassData,以实现从网络加载类。下载组成该类的字节后,它应该使用方法 ​​defineClass​​ 来创建类实例。示例实现如下:

class NetworkClassLoader extends ClassLoader { String host; int port; public Class findClass(String name) { byte[] b = loadClassData(name); return defineClass(name, b, 0, b.length); } private byte[] loadClassData(String name) { // load the class data from the connection  . . . } }

MyLoadClass (自己写类加载器)_字节码_02


import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;

import org.junit.Test;

/*
* 用自己做的类加载器加载指定目录的字节码文件,生成Class对象,进行再得出obj
* 1技术入口: 利用API中的ClassLoader类的defineClass(String name, byte[] b, int off, int len)生成一个Class对象
2为了调用defineClass(),要利用IO把字节码数据加载到一个byte[] b, 然后就可调用defineClass()方法了
*
*/
public class MyClassLoader extends ClassLoader {

public Class<?> MyLoadClass(String name) throws Exception {
// 利用IO把字节码数据加载到一个byte[] b
FileInputStream fin = new FileInputStream(name);
byte buf[] = new byte[512];
int len = 0;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
while ((len=fin.read(buf)) != -1) {
bos.write(buf, 0, len);
}
bos.close();// 把缓存中的数据全部刷到baout中
byte b[] = bos.toByteArray();
// 技术入口,调用父类ClassLoader中的defineClass()方法生成c对象
Class<?> c = this.defineClass(null, b, 0, b.length);
return c;
}

@Test
public void test1() throws Exception {
MyClassLoader loader = new MyClassLoader();
Class<?> c = loader.MyLoadClass("D:\\a\\A.class");
Object obj = c.newInstance();
System.out.println(obj);

ClassLoader loader2=obj.getClass().getClassLoader();
System.out.println("loader2: "+loader2);
}

@Test //该测试是反模式: 不同的类加载器加载的类是不能相互转换的,可理解成不同的空间
public void t2() throws Exception{
MyClassLoader loader = new MyClassLoader();
Class<?> c = loader.MyLoadClass("D:\\a\\A.class");
Object obj = c.newInstance();
//obj的类加载器是MyClassLoader, 而obj2的类加载器是AppClassLoader
A obj2 =(A) obj; //WA: 不同的类加载器加载的类是不能相互转换的
System.out.println(obj2);

}
}


举报

相关推荐

0 条评论