1.类加载器
类加载器是将java类加载进虚拟机的class类,java虚拟机提供的三种类加载器:BootStrap,ExtClassLoader,AppClassLoader
(1).这三种加载器呈树状结构排列,最上层为BootStrp,它是jvm核心的加载器,不需要其他的java类进行加载,BootStrap加载rt.jar。
(2).ExtClassLoader加载ext目录下的java类
(3).AppClassLoader是我们最常见的类加载器,加载classpath下的java类。
2.类加载器委托机制:
每个ClassLoader本身只能分别加载特定位置和目录的类,但它们可以委托其他的类装载器去加载类,这就是类加载器的委托模式。
类加载器在加载类时会先委托他的父类进行加载:首先发起类接收到未加载过的类,会委托父类对他进行加载,从父类再到BootStrap,如果还未找到,则会一级一级往下尝试,直到某个类加载器找到了字节码文件进行加载,否则抛出异常,无法加载。
3.类初始化的五种方式
(1)通过new关键创建实例。
(2)调用某个类的静态方法。
(3)访问某个类的静态属性或为其赋值。
(4)使用反射方式强行创建Class对象。
(5)初始化某个类的子类。
4.注意:类加载器之间的子父类关系与一般类之间的继承关系不同,这情况和使用泛型定义的集合类似。比如Student类继承Person类,而在ArrayList<Person> l = new ArrayList<Student>();是会报错的,因为ArrayList<Peroson>和AayList<Student>之间并非继承关系。
当一个类加载器用.getParent()方法返回null值时,要么该类加载器就是根类加载器,要么该类加载器的父类加载器是根类加载器,比如ExtClassLoader用此方法返回的就是null值。
5.自定义类加载器
由于除了根类加载器外所有的类加载器均继承自java.lang.ClassLoader类,所以可通过继承该基类来自定义类加载器。
ClassLoader类包含以下比较重要的方法:
(1)loadClass(String name,boolean resolve)。
(2)findClass(String name)。
6,自定义加加载器实例
步骤:
1.首先要明确类源文件和目标文件的路径
2.编写加密解密方法。
3.使用流对象对获取源文件,并将加密后的文件存储在另一个目录中
4.覆盖ClassLoader中的findClass方法,实现自己的类加载器
5.使用自己定义的类加载器对加密后的文件进行访问。
import java.io.*;
/*
* 类加载器实例
* 注意:有包名的类不能调用无包名的类
*/
//作为类加载器,也作为加密类
public class MyClassLoader extends ClassLoader{
public static void main(String[] args)throws Exception{
//得到要操作的源和目标
String srcPath = args[0];
// System.out.println(srcPath);
String destDir = args[1];
String destFileName = srcPath.substring(srcPath.lastIndexOf("\\")+1);
String destPath = destDir + "\\" + destFileName;
//io流
FileInputStream fis = new FileInputStream(srcPath);
FileOutputStream fos = new FileOutputStream(destPath);
//cypher method
cypher(fis,fos);
fis.close();
fos.close();
//按照正常方式调用ClassLoaderAttachment
// System.out.println(new ClassLoaderAttachment().toString());
}
//加密解密方法
public static void cypher(InputStream ips, OutputStream ops) throws Exception{
int b = -1;
while((b=ips.read())!=-1){
ops.write(b ^ 0xff);//异或,二进制1->0 0->1
}
}
private String classDir;
//自定义类加载器时,需要覆盖findClass方法
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException{//子类不能定义比父类更广泛的异常
String classFileName = classDir + "\\" + name + ".class";
try {
FileInputStream fis = new FileInputStream(classFileName);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
cypher(fis,bos);
fis.close();
byte [] bytes = bos.toByteArray();
return defineClass(bytes, 0 ,bytes.length);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
//定义空的构造函数
public MyClassLoader(){}
//定义含有name参数的构造函数
public MyClassLoader(String classDir){
this.classDir = classDir;
}
}