Class的生命周期
- loading:加载
- linking:
- verification:验证,验证的class文件是否符合JVM规范,比如java的class文件开头的cafe babe
- preparation:准备,这里的准备是对于静态变量给定
默认值
- resolution:解析,
这个我还不知道怎么解析。。。
- initializing:初始化,初始化了静态变量,这里会赋值,同时会调用静态方法
知识点:java文件被编译之后交给类加载器,这时会产生两个东西,一个是class,另一个则是操作这个class的对象
类加载器 - ClassLoader
- Bootstrap:顶层的启动类加载器,负责加载Java_HOME(JRE)目录下,lib的目录下的类库,例如Charset,是C++实现的
- Extension:拓展类加载器,负责加载Java_HOME(JRE)目录下,lib子目录下的ext的子目录的拓展类库
- App(application):应用程序类文件加载器,负责加载classpath中的类,也是我们写的程序代码会用到的一个加载器
- CustomClassLoader:自定义类加载器,负责加载自定义目录中的类,写框架都得有自己的类加载器
由于以上几个类加载器都是Launcher的内部类,具体我们可以查看Launcher源码,可以得到Bootstrap、Extension、App的加载路劲,我们可以通过一段代码来观察他们各自都负责加载哪些类
public static void main(String[] args) {
String bootClassPath = System.getProperty("sun.boot.class.path");
System.out.println(bootClassPath.replace(":", System.lineSeparator()));
System.out.println("------------------");
String extClassLoader = System.getProperty("java.ext.dirs");
System.out.println(extClassLoader.replace(":", System.lineSeparator()));
System.out.println("------------------");
String appClassLoader = System.getProperty("java.class.path");
System.out.println(appClassLoader.replace(":", System.lineSeparator()));
}
知识点:加载器其实不存在继承的父子关系,只有:谁的 类加载器 是谁,具体可以通过下面的代码来验证
public static void main(String[] args) {
Class<? extends C_1> myClass = new C_1("自定义类").getClass();
ClassLoader classLoader = myClass.getClassLoader();
System.out.println("自定义类的类加载器:" + classLoader);
ClassLoader classLoader1 = classLoader.getClass().getClassLoader();
System.out.println("自定义类的类加载器的 - 上层加载器:" + classLoader1);
}
/*
运行结果:
自定义类的类加载器:sun.misc.Launcher$AppClassLoader@18b4aac2
自定义类的类加载器的 - 上层加载器:null
*/
类加载过程-双亲委派
首先需要知道类加载器分为了4层既Bootstrap - Extension - App - CustomClassLoader,我们简称它为B-E-A-C,这四个加载器分别维护者自己的一块缓存
一个类被编程成字节码文件后,会先调用Custom.loadClass方法,把自己load进去,假如有自定义类加载器,先询问最底层的CustomClassLoader - C,如果这个加载器在内存中没有找到这个类,那么C会询问上层加载器App - A,A同样去自己维护的内存中找这个类,如果没找到,也会询问上层加载器Extension - E,同理E没找到会问Bootstrap - B,到达最顶层加载器还是没有找到这个类时,B会委托下层加载器加载这个类,但下层加载器会根据自己自己负责的领域进行加载,比如E负责加载ext中的拓展类,如果这个类不是拓展类,那E则会委托A去加载,依次类推,直到有一个加载器加载了这个类,或者没有任何一个加载器加载这个类,就会抛出ClassNotFoundException
源码过程:findInCache -> parent.loadClass -> findClass
就几个字:向上找向下委托
自定义类加载器
能干嘛?写框架、代码加密
怎么自定义?
1、extends ClassLoader
2、overwrite findClass() -> defineClass