Java虚拟机
类加载子系统
类加载过程
加载
- 通过一个类的全限定名获取定义此类的二进制字节流
- 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构
- 在内存中生成一个代表这个类的java.lang,Class对象,作为方法区这个类的各种数据的访问入口
链接
验证:确保被加载类的正确性,不会危害虚拟机自身安全。
准备:为类变量分配内存并且设置该类变量的默认初始值。不包含final修饰的static,不会为实例变量分配初始化。
解析:将常量池内的符号引用转换为直接引用的过程。
初始化
- 执行类构造器方法
()的过程。 - 无需定义,是javac编译器自动收集类中所有类变量的赋值动作和静态代码块中的语句合并而来。
()不同于类的构造器,构造器是虚拟机视角下的 ()。
几种不同的类加载器
启动类加载器(引导类加载器)
- 使用C/C++实现,嵌套在JVM内部
- 用来加载Java的核心库
- 没有父加载类,无法用.class.getClassLoader()来获取
扩展类加载器
- Java语言编写,派生于ClassLoader类
- 父加载类为启动类加载器
系统类加载器
- Java语言编写,派生于ClassLoader类
- 父加载类为扩展类加载器
- 是程序中默认的加载器,Java应用的类都有它完成加载
双亲委派机制
工作原理
- 如果一个类加载器收到了类加载请求,它不会自己先去加载,而是把这个请求委托给父类的加载器去执行。
- 如果父类加载器还存在父类加载器,则进一步向上委托,依次递归。
- 如果父类加载器可以完成类加载任务,则成功返回,否则子加载器才会尝试自己去加载。
优势
- 避免类的重复加载
- 保护程序安全,防止核心API被修改(沙箱安全机制)
一些其他信息
两个class对象是否为同一类存在两个必要条件
- 类的完整类名必须一直,包括包名
- 加载这个类的ClassLoader必须相同
对类加载器的引用
- 如果一个类型是由用户类加载器加载的,JVM将这个类加载器的一个引用作为类型信息的一部分保留在方法区中。
- 在解析一个类型到另一个类型的引用的时候,JVM需保证这两个类型的类加载器相同。
类的主动使用和被动使用
主动使用(会导致类的初始化)
- 创建实例
- 访问某个类或接口的静态变量,或者对静态变量赋值
- 调用静态方法
- 反射
- 初始化一个类的子类
- jvm启动时被标名为启动类的类
- JDK7开始提供的动态语言支持
被动使用(不会导致类的初始化)
- 其余都是被动使用