类加载
类加载器(ClassLoader)
什么是类加载器?
就是Java代码在运作,JVM在启动时,把类模板加载到内存去的工具
首先,一个Java程序真正的执行过程应该是你去调用了Java这个命令,然后程序开始执行,而执行的过程中,JVM会将很多类(.class文件,或者.jar文件)加载到当前的程序内存当中。
当你去写 类型 a = new 类型()
时,类加载器就会把加载好的模板放到堆中申请空间并占用空间,把东西加载到内存中。
类加载器的分类
真正获得类模板的过程,是通过一个叫做ClassLoader的工具来获得到的
作用:ClassLoader就是将一个存在于系统文件中的.class文件,加载到当前程序的内存当中,变成JVM中的一个对象、一个类模板,Java语言就可以识别这个Class类型
把类模板加载到工程中
问题:现有一个类的对象和他的.class文件,需要加载出这个类,生成一个对象。
defineClass()
:把这二进制文件变成我们想要的Class文件
首先自定义一个类加载器,返回的就是由Cent.class文件生成的类模板
public class MyClassLoader extends ClassLoader {
/*
//把从外部看到的.class文件变成内存中,在代码中看到的Class文件(类模板),并且用这个Class来创建对象,这个.class文件在哪不用关心
defineClass()//第二个参数数组存放的就是.class文件转换成的二进制码的数组,可以把这二进制文件变成我们想要的Class文件
*/
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
//找到那个.class文件,用文件流怼到这个文件上
FileInputStream fis = null;
try {
fis = new FileInputStream("Z:/Cent.class");
byte[] b = new byte[fis.available()];
fis.read(b);
return defineClass(name,b,0,b.length);//defindClass就是定义class的,是ClassLoader给出的
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return super.findClass(name);
}
}
ObjectInputStream使用了自己的类加载器(应用加载器),并不能加载出我们想要加载的那个类现在需要ObjectInputStream在加载我们的类时使用我们自定义的类加载器,加载其他类时使用自己的类加载器这时就需要继承ObjectInputStream,重写他的resolveClass方法了
扫描二维码关注公众号,回复:
13433497 查看本文章
重写ObjectInputStream的类加载器
public class MyObjectInputStream extends ObjectInputStream {
private ClassLoader classLoader;
public MyObjectInputStream(InputStream in) throws IOException {
super(in);
}
public MyObjectInputStream(InputStream in, ClassLoader classLoader) throws IOException {
super(in);
this.classLoader = classLoader;
}
@Override
protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
//如果可以创建对象成功就用的自己的类加载器,如果不成功,就捕获异常,用父类的类加载器创建对象
try {
return Class.forName("baidu.ali.tencent.Cent",false,this.classLoader);//第二个参数initialize:说明这个类是否必须初始化。
/*
//当然这里除了上面那样写,也可以像下面这样写,这是下面这样的写法具有局限性,让MyObjectInputStream类加载器只能加载这一种外部的类,不能加载其他类型的外部类
MyClassLoader loader = new MyClassLoader();
Class aClass = loader.loadClass("baidu.ali.tencent.Cent");
return aClass;
*/
} catch (Exception e) {
return super.resolveClass(desc);
}
}
}
ublic class HomeworkDemo {
public static void main(String[] args) {
MyClassLoader loader = new MyClassLoader();
try {
Class clazz = loader.loadClass("baidu.ali.tencent.Cent");//用自己定义的类加载器拿到了类模板了,加载的只是一个类型,还并不是对象
/*
ObjectInputStream使用了自己的类加载器(应用加载器),他只能加载写在工程里的类,并不能加载出我们想要加载的那个类
现在需要ObjectInputStream在加载我们的类时使用我们自定义的类加载器,加载其他类时使用自己的类加载器
这时就需要继承ObjectInputStream,重写他的resolveClass方法了
*/
ObjectInputStream ois = new MyObjectInputStream(new FileInputStream("Z:/object.lgc"),loader);//用loader把类型加载出来
Object object = ois.readObject();//成功的将外部我们想要加载的类加载进来了,生成了object对象
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}