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 . . . } }
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);
}
}