一:class类装载验证流
1:加载
A:装载类的第一阶段,
B:取得类的二进制流
C:转为方法区的数据结构(类的相关信息都实存在方法区中的)
D:在java堆中生成对应的java.lang.Class对象
加载阶段完成之后二进制字节流就按照虚拟机所需的格式存储在方区去中。-
2:连接
- A:验证
目的:保证Class流格式正确:
a:文件格式验证
是否以0xCAFEBABE开头
版本号是否合理
b:元数据验证
是否有父类
继承了final类
非抽象类是否实现了所有的抽象方法
c:字节码验证(比较复杂)
运行检查
栈数据类型和操作码数据参数吻合
跳转指令到合理的位置
d:符号引用验证
常量池中描述类是否存在
访问的方法或者字段是否具有足够的权限 - B:准备
分配内存,并为类设置初始值(方法区中)
public static int v =1;
在准备阶段中,v会被值为0;
在初始化的<clinit>中才会被值为1;
对于static final类型,在准备阶段就就会被赋上正确的值
public static final int v =1; - C:解析
将符号引用替换直接引用;
什么是符号引用;什么是直接引用
字符串引用对象不一定被加载;
指针或者地址偏移量引用对象一定在内存
- A:验证
3:初始化***
A:执行类构造器<clinit>
--static 变量 赋值语句
--static{}语句会被执行
B:子类的<clinit>调用前保证父类的<clinit>被调用
C:<clinit>是线程安全的;
二:ClassLoader
1:什么是类装载器ClassLoader?***
a:ClassLoader是一个抽象类
b:ClassLoader的实例将读入Java字节码将类装载到JVM中
c:ClassLoader可以定制,满足不同字节码流获取方式
d:ClassLoader负责类装载过程中的加载阶段;
2: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)
寻找已经加载的类
-
3:ClassLoader的种类:
A:BootStrap ClassLoader (启动ClassLoader)
B:Extension ClassLoader (扩展ClassLoader)
C:App ClassLoader (应用ClassLoader/系统ClassLoader)
D:Custom ClassLoader(自定义ClassLoader)
每个ClassLoader都有一个Parent作为父亲
正常情况下:自底向上检查类是否已经加载,自顶线下尝试加载类
-
4:JDK中ClassLoader默认代理模式
概念:从1.2版本开始,Java引入了双亲委托模型,从而更好的保证Java平台的安全。在此模型下,当一个装载器被请求装载某个类时,它首先委托自己的parent去装载,若parent能装载,则返回这个类所对应的Class对象,若parent不能装载,则由parent的请求者去装载。
A:协同模式:
类的加载从上往下的;找类时是从底向上的方式;
B:默认的设计模式的问题:
ClassLoader:采用双亲模式问题:
顶层的ClassLoader,无法夹杂底层ClassLoader的类;
C:解决:
Thread.setContextClassLoader();
--上下文加载器
--是一个角色
--用来解决顶层ClassLoader无法访问底层ClassLoader的类问题
--基本思想是:在顶层ClassLoader中,传入底层ClassLoader的实例;
D:双亲模式的破坏:
双亲模式是默认的模式,但是不是必须这么做;
Tomcat的webAppClassLoader,就会现在加载自己的Class,
OSGi的ClassLoader形成网状结构,根据需要自由加载Class;
子类方法初始法之前,先加载父类的构造方法; - 4:热部署和热加载
A:基本概念:在应用运行的时升级软件,无需重新启动的方式有两种,热部署和热加载。
热部署:对于Java应用程序来说,热部署就是在服务器运行时重新部署项目,
热加载:热加载即在在运行时重新加载class,从而升级应用。
B:实现原理:
热加载的实现原理主要依赖java的类加载机制,在实现方式可以概括为在容器启动的时候起一条后台线程,定时的检测类文件的时间戳变化,如果类的时间戳变掉了,则将类重新载入。
对比反射机制,反射是在运行时获取类信息,通过动态的调用来改变程序行为;
热加载则是在运行时通过重新加载改变类信息,直接改变程序行为。
热部署原理类似,但它是直接重新加载整个应用,这种方式会释放内存,比热加载更加干净彻底,但同时也更费时间。
补充: 类的加载方式
1):本地编译好的class中直接加载
2):网络加载:java.net.URLClassLoader可以加载url指定的类
3):从jar、zip等等压缩文件加载类,自动解析jar文件找到class文件去加载util类
4):从java源代码文件动态编译成为class文件