类从编译到执行的过程
- 编译器将 .java 源文件编译为 .class 字节码文件
- ClassLoader将字节码转换为JVM中的 class对象
- JVM利用class对象实例化对象
ClassLoader在java中有着非常重要的作用,它主要工作在class装载的加载阶段,其主要作用是从外部系统获得class二进制数据流,它是java的核心组件所有的class都是由ClassLoader进行加载的,ClassLoader负责通过将class文件里的二进制数据流装进系统,然后交给java虚拟机进行连接,初始化等操作。
种类
- BootStrapClassLoader:C++ 编写,加载核心库java.*
- ExtClassLoader:Java编写,加载扩展库javax.*
- AppClassLoader:Java编写,加载程序所在目录(class.path)
- 自定义ClassLoader:Java编写定制加载
自定义ClassLoader的实现
关键函数:
protected Class<?> findClass(String name) throws ClassNotFoundException {
throw new ClassNotFoundException(name);
}
@Deprecated
protected final Class<?> defineClass(byte[] b, int off, int len)
throws ClassFormatError
{
return defineClass(null, b, off, len, null);
}
简单实现
import java.io.*;
/**
* 2020/7/9 11:01 下午
* @author dogggg
* 简单的自定义classLoader
*/
public class MyClassLoader extends ClassLoader{
/** 路径 */
private String path;
/** 名称 */
private String classLoaderName;
/** 全参构造函数 */
public MyClassLoader(String path, String classLoaderName) {
this.path = path;
this.classLoaderName = classLoaderName;
}
@Override
public Class findClass(String name){
byte[] b = loadClassData(name);
return defineClass(name,b,0,b.length);
}
/** 用于加载类文件 */
private byte[] loadClassData(String name) {
/** 全路径1 */
name = path + name + ".class";
/** jdk1.8新特性,不用手动关闭 */
try(InputStream in =
new FileInputStream(new File(name));
ByteArrayOutputStream out = new ByteArrayOutputStream();
) {
/** 进行循环 */
int i = 0;
while ((i = in.read()) != -1){
/** 写文件 */
out.write(i);
}
/** 进行返回 */
return out.toByteArray();
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
}