主题:class类的加载过程
内容: 摘要:class类的load(加载),linking(链接) ,initializing(初始化)
详细:
类加载的过程,load的操作在java中使用双亲委托机制进行加载,分为四个加载器,bootstrap(根类加载器,由c++实现,如果获取该类加载器的话,会看到值为null,因为由c++实现,它在java中无具体对象),ext(拓展类加载器),applocation(应用类加载器,即classpath路径下的类,比如项目里面自己写的所有类),custom(用户自定义类加载器)。
custom的父加载器为application类加载器,application类加载器的父加载器为ext类加载器,ext类加载器的父加载器是bootstrap类加载器,这里所说的父,指的是custom,application,ext等类加载器的实现类的成员变量有一个属性名称定义为parent的上层类加载器(UML的父关系),并不是继承关系,具体的类的继承,它们的根都为classload类。
值得注意的是,custom,ext,application等类加载器都是由bootstrap类加载器加载。这里的关系稍微复杂,需要注意区分了。
双亲委托机制的主要作用是安全,想象一下,如果不这样设置,我们便可以通过技术手段,来替换掉sun的一些核心类了,从而在这个里面增加一些功能,来窃取一些机密信息。比如,我们可以通过改一些开源框架,重新发布,自己发布一些框架等,达到某种目的。
java设计的整个加载来看,是lazyloading,即懒加载。
lazyloading加载类的5种情况:
new getstatic putstatic invokestatic 这些指令会进行类加载,final定义的常量除外
java.lang.reflect对类进行反射调用时
初始化子类时,父类首先初始化
虚拟机启动时,被执行的主类必须加载
动态语言支持java.lang.invoke.MethodHandle解析的结果为REF_getstatic REF_putstatic REF_invokestatic的方法句柄时,该类必须初始化(这条我没有实验)
自定义类加载器:
作用:比如开源框架加载自己指定目录下的一些类,这些路径加载必须由自定义加载器指定路径才能找到。
双亲委托机制查找内存有无和寻找地址进行加载的过程结束,没有找到类的情况下,则会抛出classNotFound异常
我们要实现自定义的类加载器,则重写findClass,让它不要抛异常(具体看源码),即可实现。
public class CustomClassLoad extent ClassLoad{
@Overwriter
findClass(){
defineClass(byte[]) ---> class clazz (将class字节流转化为类class对象后返回)
}
}
类加载的双亲委托机制是可以被破坏的。重写ClassLoad类中的loadClass方法即可,双亲委托机制就是在此方法中实现的。
重写loadClass的作用:比如热加载,tomcat中也重写了。 在jdk1.2之前是必须要重写loadClass方法的,1.2以后由jdk实现了双亲委托的设计机制,但是仍可以被重写破坏。