类装载器
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被替换后,系统无需重启,替换的类立即生效。相关文章推荐
- 网路类装载器客户端
- Java的类装载器和命名空间
- java类装载器原理
- Android 装载器---在应用程序中使用装载器
- java 类装载器
- android基于类装载器DexClassloader设计“插件框架”
- java之jvm学习笔记二(类装载器的体系结构)
- java之jvm学习笔记二(类装载器的体系结构)
- Java虚拟机有两种类装载器
- 类装载器学习
- 浅析JVM类装载器
- 网路类装载器客户端(0825写的)
- 恢复GRUB操作系统引导装载器
- java类装载器原理
- Android 装载器---启动装载器
- 类装载器DexClassLoader (android内核剖析)
- java之jvm学习笔记五(实践写自己的类装载器)
- java之jvm学习笔记二(类装载器的体系结构)
- Android中的类装载器DexClassLoader