JVM系列二:(class类的加载、链接、初始化)

278 阅读3分钟

主题: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实现了双亲委托的设计机制,但是仍可以被重写破坏。