您的位置:首页 > 其它

类装载器

2017-12-22 00:00 190 查看

一、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;

> 解析



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作为父亲





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

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底层的类?



解决: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被替换后,系统无需重启,替换的类立即生效。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  JVM 类装载器