参考文章:
什么是JVM? JVM和一些相关概念的关系
- jvm中文全称为java虚拟机 是java字节码运行的平台
- jvm和jdk、jre的关系:
- jre是java最小运行环境,包含JVM和java核心类库
- jdk是java最小开发环境由jre和java工具组成
JAVA内存模型
-
公有数据区,线程共享
- 堆:存放对象,静态变量 是垃圾回收的发挥作用的区域
- 方法区(java8以前):存放类信息,常量池
-
私有数据区,线程私有
- jvm栈/虚拟机栈
- 每个线程有一个jvm栈,存储帧
- 帧
- 每个线程有一个jvm栈,存储帧
- PC寄存器 记录线程运行到达的位置(指令地址)
- 本地(native)方法栈:本地方法不由JVM管理
- jvm栈/虚拟机栈
-
本地内存 /堆外内存
- 直接内存
- 元空间
- 方法区(java8以后)
垃圾回收(GC)
-
什么是垃圾?
- 即无法被使用的变量
-
识别垃圾
-
引用计数
-
对象被引用一次,计数+1,引用次数为0,就可以回收
-
例子:String s= new String(“dpz”); //此时引用计数为1
- s=null; //此时引用计数为0
-
问题:循环引用 例子是转载的
-
下面这个类包含一个自身类型的非static变量,运行到最后 a、b的引用计数都为1,可实际上a、b已经无法使用了!
-
public class TestRC {
TestRC instance;
public TestRC(String name) {
} public static void main(String[] args) {
// 第一步
A a = new TestRC(“a”);
B b = new TestRC(“b”); // 第二步
a.instance = b;
b.instance = a; // 第三步
a = null;
b = null;
}
}
-
-
可达性分析
- 引用链的方式判断对象是否存活
- 从被称作GC ROOT的对象出发,指向下一个节点
- 当一个对象不在任意一条引用链上时,这个对象即为垃圾
- GC ROOT是什么?如何指?
- 以下几种对象可以作为GC ROOT
- 虚拟机栈(栈帧中的本地变量表)中引用的对象
- 示例代码中,a作为GC ROOT指向对象,a指向空后,对象不在链上,成为垃圾
- 方法区中类静态属性引用的对象
- 下面的例子,s作为GC ROOT 对象存活
-
public static Test s; public static void main(String[] args) { Test a = new Test(); a.s = new Test(); a = null; } }
- 方法区中常量引用的对象
- 本地方法栈中 JNI(Native 方法)引用的对象
- 虚拟机栈(栈帧中的本地变量表)中引用的对象
- 以下几种对象可以作为GC ROOT
- 引用链的方式判断对象是否存活
-
-
垃圾回收算法
- 标记清除法
- 流程
- 标记可回收对象(垃圾)
- 回收
- 问题:内部碎片 //连续内存
- 流程
- 复制算法 为了解决标记清除的内部碎片问题
- 流程
- 把内存分为两块 A和B
- A使用标记清除后,再把对象复制到B(连续排列)
- AB身份反转
- 问题:
- 内存直接少了一半 太浪费了
- 还得来回复制对象 效率太低了
- 流程
- 标记整理(压缩)
- 在标记清除后,将内存中的对象都排列到一起,去除碎片
- 问题:效率太低了
- 分代收集
- 将堆区域分为几“代”,用不同的方式回收
- 老年代和新生代(默认比例2:1),java8之前还有永久代
- 新生代分为Eden区 from Survivor区(S0) to Survivor区(S1)(8:1:1)
- 新生代的回收称为Young GC或Minor GC,老年代的回收称为Old GC或full GC
- 老年代一般使用标记整理算法回收
- 为什么这样做?
- 大部分对象生命周期很短,很快就被回收了
- 如何分配对象
- 对象首先分配在新生代的Eden区
- Eden区使用比例到达阈值时,触发Minor GC (大部分对象被回收)
- 经过Minor GC后Eden区留下的对象被放到S0区,对象年龄(Minor GC次数)+1
- 下一次Minor GC时,Eden区和S0区存活的对象一起移到S1区,对象年龄+1,S0 S1身份互换
- 再次触发Minor GC重复上一步
- 当对象年龄达到阈值,从S0(S1)移动到老年代
- *当某个对象需要大量连续内存的时候会直接分配在老年代,否则来回移动开销较大
- 在 S0(或S1) 区相同年龄的对象大小之和大于 S0(或S1)空间一半以上时,则年龄大于等于该年龄的对象也会晋升到老年代。//空间不足
- 问题:
- stop the world(STW)
- 啥是STW? 顾名思义,只有GC线程在工作,其他线程挂起(stop) //在生产中出现这种情况可不好哦 服务器直接不响应请求了
- 老年代满了,触发Full GC 同时回收老年代和新生代,导致STW,开销大
- stop the world(STW)
- 将堆区域分为几“代”,用不同的方式回收
- 标记清除法
-
垃圾收集器
- 新生代
- Serial
- ParNew
- Parrallel Scavenge
- G1
- 老年代
- CMS
- Parallel Old
- Serial Old
待续…
- 新生代