类装载器

一、class装载验证流程

    1、加载

            > 装载类的第一个阶段

            > 取得类的二进制流

            > 转为方法区数据结构

            > 在Java堆中生成对应的java.lang.Class对象

    2、链接

            > 验证

                目的:保证Class流的格式是正确的

                文件格式的验证

                    是否以0xCAFEBABE开头

                    版本号是否合理

                元数据验证

                    是否有父类

                    继承了final类?

                    非抽象类实现了所有的抽象方法

                字节码验证 (很复杂)

                    运行检查

                    栈数据类型和操作码数据参数吻合

                    跳转指令指定到合理的位置

                符号引用验证

                    常量池中描述类是否存在

                    访问的方法或字段是否存在且有足够的权限

                注:不加标识符,默认包内访问

            > 准备

                    分配内存,并为类设置初始值 (方法区中)

                        public static int v=1;

                        在准备阶段中,v会被设置为0

                        在初始化的<clinit>中才会被设置为1

                        对于static final类型,在准备阶段就会被赋上正确的值

                        public static final  int v=1;

            > 解析

173426_TXUq_3144678.png

    3、初始化

        > 执行类构造器<clinit>

            static变量 赋值语句

            static{}语句

        > 子类的<clinit>调用前保证父类的<clinit>被调用

        > <clinit>是线程安全的

二、什么是类装载器ClassLoader

    1、ClassLoader是一个抽象类

    2、ClassLoader的实例将读入Java字节码将类装载到JVM中

    3、ClassLoader可以定制,满足不同的字节码流获取方式

    4、ClassLoader负责类装载过程中的加载阶段

三、JDK中ClassLoader默认设计模式

    1、ClassLoader的重要方法

public Class<?> loadClass(String name) throws ClassNotFoundException
方法描述:载入并返回一个Class
protected final Class<?> defineClass(byte[] b, int off, int len)
方法描述:定义一个类,不公开调用
protected Class<?> findClass(String name) throws ClassNotFoundException
方法描述:loadClass回调该方法,自定义ClassLoader的推荐做法
protected final Class<?> findLoadedClass(String name) 
方法描述:寻找已经加载的类

    2、分类

BootStrap ClassLoader (启动ClassLoader)
Extension ClassLoader (扩展ClassLoader)
App ClassLoader (应用ClassLoader/系统ClassLoader)
Custom ClassLoader(自定义ClassLoader)

每个ClassLoader都有一个Parent作为父亲

174109_OR5O_3144678.png

174123_tCV3_3144678.png

                说明:类加载是从顶向下的

    3、强制在apploader中加载

        在查找类的时候,先在底层的Loader查找,是从下往上的。Apploader能找到,就不会去上层加载器加载。

public static void main(String args[]) throws Exception {
	ClassLoader cl=FindClassOrder2.class.getClassLoader();
	byte[] bHelloLoader=loadClassBytes("geym.jvm.ch6.findorder.HelloLoader");
	Method md_defineClass=ClassLoader.class.getDeclaredMethod("defineClass", byte[].class,int.class,int.class);
	md_defineClass.setAccessible(true);
	md_defineClass.invoke(cl, bHelloLoader,0,bHelloLoader.length);
	md_defineClass.setAccessible(false);
	
	HelloLoader loader = new HelloLoader();
	System.out.println(loader.getClass().getClassLoader());
	loader.print();
}
-Xbootclasspath/a:D:/tmp/clz

    4、问题

            问题:BootClassLoader如何访问ExtClassLoader/AppClassLoader底层的类?

174531_IDAa_3144678.png

            解决:Thread. setContextClassLoader()

            上下文加载器

            是一个角色

            用以解决顶层ClassLoader无法访问底层ClassLoader的类的问题

            基本思想是,在顶层ClassLoader中,传入底层ClassLoader的实例

    5、双亲模式的破坏

        双亲模式是默认的模式,但不是必须这么做。 

        Tomcat的WebappClassLoader 就会先加载自己的Class,找不到再委托parent(模式破坏,应该是自顶向下加载) 。

        OSGi的ClassLoader形成网状结构,根据需要自由加载Class(模块化热加载:一会Class进来,一会又离开,传统Parent加载模式不适用,加载机制很复杂)。

四、打破常规模式

    jdk的ClassLoader未强制使用其parent双亲模式,可以重载ClassLoader,例如破坏jdk的ClassLoader双亲模式的产物:

        1、tomcat中Webapp的ClassLoader先加载自己的; 

       2、OSGI热部署,网状结构访问模式(让程序有多种可能性,使程序架构更加灵活,有无限的想象空间)。

五、热替换

    含义: 当一个class被替换后,系统无需重启,替换的类立即生效。

转载于:https://my.oschina.net/Howard2016/blog/1593833

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值