JAVA虚拟机中可以安装多个类加载器,系统默认三个主要类加载器,每个类负责加载特定位置的类:
BootStrap,ExClassLoader,AppClassLoader
类加载器也是JAVA类,因为它是JAVA类加载器本身要被类加载器加载,显然必须有第一个加载器不是JAVA类,这正是BootStrap。
JAVA虚拟机中的所有类加载器采用具有斧子关系的树型结构进行组织,在实例化每个加载器对象的时候,需要为其制定一个父级类加载器对象或者默认采用系统类加载器为其父类加载。
类加载器的委托机制:
首先当前线程的类加载器去加载线程中的第一个类。
如果类A中引用了类B,JAVA虚拟机将使用加载类A的类加载器来加载类B。
还可以直接调用ClassLoader.loadClass()方法来指定某个类加载器去加载某个类。
当所有祖宗类加载器没有加载到类,回到发起者类加载器,还加载不了,则抛出ClassNotFoundException.
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import org.omg.CORBA_2_3.portable.OutputStream;
public class MyClassLoader extends ClassLoader{
public static void main(String[] args) throws Exception {
//源文件和目的文件都用软编码写好
String srcPath=args[0];
String destDir=args[1];
FileInputStream fis = new FileInputStream(srcPath);
String destFileName=srcPath.substring(srcPath.lastIndexOf('\\')+1);
String destFilePath=destDir+"\\"+destFileName;
FileOutputStream fos = new FileOutputStream(destFilePath);
}
//对要加载的类文件进行加密,这里采用比较简单的方式加密
private static void cypher(InputStream ips,OutputStream ops) throws Exception{
int b=-1;
//如果二进制文件中是1就改为0,如果二进制文件中是0就改为1
while((b=ips.read())!=-1){
ops.write(b^0xff);
}
}
private String classDir;
@Override
//复写了findClass方法,如果父类找不到文件就会使用自定义类加载器的方法进行加载
protected Class<?> findClass(String name) throws ClassNotFoundException {
String classFileName=classDir+"\\"+name+".class";
FileInputStream fis = null;
fis= new FileInputStream(classFileName);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
//对文件进行解密
cypher(fis,bos);
fis.close();
byte[] bytes= bos.toByteArray();
return difineClass(bytes,0,bytes.length);
return super.findClass(name);
}
private Class<?> difineClass(byte[] bytes, int i, int length) {
// TODO Auto-generated method stub
return null;
}
public MyClassLoader(){
}
//将文件目录传递进来
public MyClassLoader(String classDir){
this.classDir=classDir;
}
}
学习感悟:类加载器的委托机制是先在父类中找看是否可以找到相应的文件,如果找不到再回到发起者中找,如果不知道这个,会造成很多错误。