➢编译器将Robot.java源文件编译为Robot.class字节码文件 ➢ClassLoader将字节码转换为JVM中的Class <Robot>对象 ➢JVM利用Class <Robot>对象实例化为Robot对象
Classloader在Java中有着非常重要的作用 它主要工作在Class装载的加载阶段,所有的Class都是由ClassLoader进行加载的,ClassLoader负责通过将Class文件里的二进制数据流或者是从系统外部获得Class二进制数据流装载进系统,然后交给Java虚拟机进行连接、初始化等操作。
ClassLoader里面包含了许多方法制定了加载流程和方式
其中loadClass是比较重要的,可以根据类名查找当前ClassLoader是否加载了该class,如果有的话就返回类的class实例,找不到就会返回null
手写ClassLoader
package jvm;
import java.io.*;
public class MyClassLoader extends ClassLoader{
private String path;
private String MyClassLoaderName;//定义自己的ClassLoader名字 实际上没啥用
public MyClassLoader(String path, String MyClassLoaderName) {
this.path = path;
this.MyClassLoaderName = MyClassLoaderName;
}
@Override
//用于寻找类文件
public Class findClass(String name){
byte[] b=loadClassData(name);
return defineClass(name,b,0,b.length);
}
//用于加载class文件为字节码
private byte[] loadClassData(String name) {
String url=path+name+".class";
InputStream inp=null;
ByteArrayOutputStream out=null;
try {
inp=new FileInputStream(new File(url));
out=new ByteArrayOutputStream();
int i=0;
while ((i=inp.read())!=-1){
out.write(i);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
try{
out.close();
inp.close();
}catch (Exception e)
{
e.printStackTrace();
}
}
return out.toByteArray();
}
}
package jvm;
public class ClassLoaderCheck {
public static void main(String[] args) throws Exception {
MyClassLoader myl=new MyClassLoader("C:\\Users\\Zyh\\Desktop\\","ZyhClassLoader");//我的桌面C:\\Users\\Zyh\\Desktop\\上有个ClassTest.class文件,ZyhClassLoader没有啥左右就是给我的classloader起个名字而已
Class c = myl.loadClass("ClassTest");
System.out.println(c.getClassLoader());
c.newInstance();
}
}
可以加载任意字节流,比如访问远程网络加载二进制流并生成我们需要的类 我们也可以对某些敏感的class进行加密,自定义findClass()进行解密处理
隐式加载:new 显式加载:loadClass,forName等
举例子:
forName是执行了初始化的有时候我们需要得到已经初始化的class比如注册mysql驱动
有时候我们为了加快初始化速度会使用lazy-load(比如springIOC读取bean的配置文件),而使用ClassLoader不用进行链接和初始化省去执行static方法等的时间花费,加快加载速度,等需要时候再进行使用