执行Class文件的环境
虚拟机结构
虚拟机是执行Class文件的环境,通过类加载子系统加载进来,其一般包括:运行时数据区域、执行引擎(即时编译器、垃圾回收器)、本地库接口、本地方法库。
Class文件格式
此二进制格式文件独立于特定的硬件与操作系统。
任何语言,只要能被编译成Class文件,就可以被Java虚拟机识别并执行。
每一个Class文件中都对应着唯一的类或者接口的定义信息。包含的信息有:
- 副、主版本号
- 常量池计数器、常量池
- 类和接口层次的访问标志
- 接口计数器、接口表
- 字段计数器、字段表
- 方法计数器、方法表
- 属性计数器、属性表
总之,通过已定规则,将类或接口的信息转换成Class文件格式。
类的生命周期
一般指:Java文件被加载到Java虚拟机内存中到从内存中卸载的过程。
大致如下:
- 加载:查找并加载Class文件
- 链接:包括验证、准备和解析
验证:确保被导入类型的正确性
准备:为类的静态字段分配字段,并用默认值初始化这些字段
解析:虚拟机将常量池内的符号引用替换为直接引用 - 初始化:将类变量出事为正确初始值
类加载子系统
有2种类加载器:系统加载器和自定义加载器。其中,系统加载器包括下面3种:
- Bootstrap ClassLoader(引导类加载器)
C/C++实现,加载指定的JDK的核心类库 - Extensions ClassLoader(拓展类加载器)
用于加载Java的拓展类 - Application ClassLoader(应用程序类加载器)
运行时数据区域
- 方法区
线程共有 - Java堆
线程共有 - Java虚拟机栈
线程私有,有OOM,保存Java程序的栈帧 - 本地方法栈
线程私有,有OOM,保存Native程序的栈帧 - 程序计数器
线程私有,没有OOM,针对Java程序(Native程序不管)
对象的创建
通过new指令来完成一个对象的创建。有如下操作:
- 判断对象对应的类是否加载、链接和初始化
- 分配内存
- 处理并发安全问题
- 初始化分配到的内存空间
- 设置对象头
- 执行init方法进行初始化
对象的堆内存布局
- 对象头
Mark Word、元数据指针
Mark Word:hash、age(对象的分代年龄)、biased_lock(偏向锁标识位)… - 实例数据
- 对齐填充
oop-klass模型
用来描述Java对象实例的一种模型。
- OOP(Ordinary Object Pointer)
指的是普通对象指针,用来表示对象的实例信息。 - klass
用来描述元数据
垃圾标记算法
Java中的引用
- 强引用
GC时,不回收 - 软引用
GC时,不够用才回收 - 弱引用
GC时,遇到就回收 - 虚引用
GC时,遇到就回收,被回收时会收到一个系统通知。
引用计数法
iOS中Objective-C中使用,不能解决循环引用的问题。
根搜索算法
GC Roots
- Java栈中引用的对象
- 本地方法栈中JNI引用的对象
- 方法区中运行时常量池引用的对象
- 方法区中静态属性引用的对象
- 运行中的线程
- 由引导类加载器加载的对象
- GC控制的对象
Java对象在虚拟机中的生命周期
- 创建阶段(Created)
分配空间——构造对象——构造方法 - 应用阶段(In Use)
至少有一个强引用,或者显示的使用软、弱、虚引用 - 不可见阶段(Invisible)
在程序中找不到对象的任何强引用。但对象仍可能被特殊的强引用GC Roots持有着,比如对象被贝蒂方法栈中JNI引用或运行中的线程引用等。 - 不可达阶段(Unreachable)
在程序中找不到对象的任何强引用,并且垃圾收集器发现对象不可达。 - 收集阶段(Collected)
垃圾收集器发现对象不可达,并且一记准备好要对对象的内存空间重新进行分配,如果对象重写了finalize方法,则会调用该方法。 - 终结阶段(Finalized)
在对象执行完finalize对象后仍然是不可达状态,或者没有重写此方法,则对象进入终结阶段,并等待被回收。 - 对象空间重新分配阶段(Deallocated)
垃圾收集算法
标记-清除算法
- 标记阶段
标记处可以回收的对象 - 清除阶段
回收被标记的对象所占用的空间
缺点:效率低、易碎片。
复制算法
将内存空间分为2部分,每次只使用其中一个区域,在回收时,遍历当前使用区域,将存活的对象复制到另一个区域,然后将当前可回收对象进行回收。
缺点:利用率低。
标记-压缩算法
在标记可回收的对象后将所有存活的对象压缩到内存的一端,是它们紧凑地排列在一起,然后对边界以外的内存进行回收。
分代收集算法
对不同生命周期的对象采取不同的收集策略,根据生命周期长短将它们分别放到不同的区域,并在不同区域采用不同的收集算法。
Java堆区基于分代的概念,分为新生代与老年代,其中新生代还可以细分为Eden空间、From Survivor空间和To Survivor空间。
分代收集
- Minor Collection:新生代垃圾回收
当执行一次Minor Collection时,Eden空间的存活对象会被复制到To Survivor空间,在From Survivor空间存活的对象也会被复制到To Survivor空间。
当对象存活年龄(经历一次GC涨一岁)超过阈值(-XX:MaxTenuringThreeshold)、To Survivor空间已满,则直接复制到老生代(晋级成功)。
此时,Eden空间与From Survivor空间都会被清空,新生代的对象都在To Survivor空间中。
最后,From Survivor空间与To Survivor空间互换位置,以确保To Survivor空间是空的。 - Full Collection:老年代垃圾收回
老生代会采用标记-压缩算法或标记-清除算法。