类加载器的作用在此不多说,直接上代码;
①说明:定义要被自定义加载器加载器的类。
package csdn.sub01;
public class MyTest {
static {
System.out.println("hello!!!");
}
}
②说明:自定义类加载器,通过继承ClassLoader类,重写loadClass或者findClass方法均可,这里我选择使用重写findClass方法
代码如下:
package csdn.sub01;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
public class MyClassLoader extends ClassLoader{
private String byteCodePath; //要加载的字节码文件的路径
public MyClassLoader(String byteCodePath){
this.byteCodePath = byteCodePath;
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
String fileName = byteCodePath + name + ".class"; //拼接要加载的字节码文件的绝对路径
BufferedInputStream in = null;
ByteArrayOutputStream out = null;
try {
in = new BufferedInputStream(new FileInputStream(fileName));
out = new ByteArrayOutputStream();
int len = 0;
byte[] data = new byte[1024]; //1kb
while((len = in.read(data)) != -1){
out.write(data,0,len);
}
byte[] bytes = out.toByteArray(); //获取到字节码的二进制流
Class<?> aClass = defineClass(null, bytes, 0, bytes.length); // 调用父类方法获取Class对象
return aClass;
}catch (Exception e){
e.printStackTrace();
}finally {
// 释放资源
if (in != null){
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (out != null){
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
}
③javac编译MyTest文件,并把得到的class文件复制到d盘目录下
④定义测试类
package csdn.sub01;
public class ClassLoaderTest {
public static void main(String[] args)throws Exception {
MyClassLoader myClassLoader = new MyClassLoader("d:/"); //要加载的路径
Class<?> myTest = myClassLoader.findClass("MyTest");
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader(); // 获取应用程序类加载器
Class<?> aClass = systemClassLoader.loadClass("csdn.sub01.MyTest");
//注意主动用加载器加载class文件不会触发类cinit方法的执行,所以需通过创建该类的对象等方式类查看MyTest类的静态代码块是否执行
System.out.println(myTest == aClass); //比较是否相等
Object o = myTest.getConstructors()[0].newInstance(null);
Object o1 = aClass.getConstructors()[0].newInstance(null);
}
}
输出结果:
由此自定义类加载器就完成了!!!