ClassLoader
是整个JVM运行机制的入口,程序通过ClassLoader将编译好的字节码文件加载到内存中,生成Class,进而创建对象,之后才能进行各种运算、解析,最终生成机器码提交到操作系统中;
ClassLoader的作用是将字节码文件加载到内存中,所以要先有字节码文件
1、创建java文件
public class FileJava {
public FileJava() {
System.out.println("hhehhehe");
}
}
特别需要
注意
的是:
该文件不能在idea中创建
,否则会在运行程序的时候被编译到用户类路径(classpath)下,那么还是会被AppClassLoader加载;
而且如果将其建立在IDEA中,在编译完该文件之后,其class文件会存在于该项目的src同等阶级的out/production/目录下,如果使用的是该class路径,运行时也会报java.lang.NoClassDefFoundError错误;
我将该文件建立在了
D盘下的ClassLoaderBySelf文件夹
下;
2、编译java文件为字节码文件
使用命令:
javac FileJava.java
3、创建自定义ClassLoader,并继承ClassLoader
ClassLoader具体的工作流程主要是通过两个方法完成类加载的,分别是findClass和defineClass;
findClass根据路径加载字节码文件,然后交给defineClass,再把字节码文件转化为class。
自定义ClassLoader需要开发者对findClass方法进行重写,完成加载字节码文件的操作,之后再将字节数据传给ClassLoader的defineClass方法即可;
import java.io.*;
public class MyClassLoader extends ClassLoader {
private String myPath;//文件路径
public MyClassLoader( String myPath) {
this.myPath = myPath;
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException{
//name是文件名
String classPath=myPath+name+".class";
//System.out.println(classPath);
InputStream in=null;
ByteArrayOutputStream out=null;
try {
in = new FileInputStream(classPath);
out=new ByteArrayOutputStream();
int value=-1;
while ((value=in.read())!=-1){
out.write(value);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if(out!=null){
out.close();
}
if(in!=null) {
in.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
byte[] bytes= out.toByteArray();
return defineClass(name,bytes,0,bytes.length);
}
}
4、进行测试
实例化MyClassLoader,并通过该实例化对象加载字节码文件获取Class对象
public class Test {
public static void main(String[] args) {
MyClassLoader myClassLoader=new MyClassLoader("D:/ClassLoaderBySelf/");
try {
Class classz=myClassLoader.loadClass("FileJava");
System.out.println(classz);
System.out.println(classz.getConstructor().newInstance());
} catch (Exception e) {
e.printStackTrace();
}
}
}
截图: