Copyright © 2015 Powered by MWeb, Theme used GitHub CSS.

程序计数器
Java虚拟机栈
本地方法栈
Java堆
线程共享
几乎所有的对象实例都在堆中分配。
逃逸分析、标量替换-->栈上分配

新生代:老年代 = 1:2
Eden:S0:S1 = 8:1:1
方法区
辣鸡回收需要做的3件事情
上面JVM运行时数据区中线程私有变量(本地方法栈、JVM虚拟机栈、程序计数器)会随着方法执行的完成而自动释放内存,所以这部分的内存不需要考虑回收。需要考虑回收的内存主要就是堆内存与方法区,只有在程序运行的时候才知道会创建哪些对象,哪些需要回收。
--
判断对象是否存活
程序计数器
给对象添加一个引用计数器,每当有一个地方引用它时,计数器的值就+1,当引用失效时,计数器的值-1.
但是主流的Java虚拟机里面并没有使用这种方式,最主要的原因是它很难解决对象之间相互循环引用的问题。
可达性分析(GC Roots)
使用最多的是这种方式。
这种算法的思路就是,选择一个根节点,从这个节点往下搜索,搜索过程中走过的路径称为引用链,当一个对象到根节点没有引用链存在时,也就是不可达,这种对象就是辣鸡对象。
哪些对象可以作为GC Roots
引用的类型
强引用:
Object obj =new Object(); // 强引用
obj = null;//这时候为垃圾回收器回收这个对象,至于什么时候回收,取决于垃圾回收器的算法
软引用:
String value = new String(“sy”);
SoftReference sfRefer = new SoftReference (value );
sfRefer .get();//可以获得引用对象值
弱引用
String value = new String(“sy”);
WeakReference weakRefer = new WeakReference(value );
System.gc();
weakRefer.get();//null
虚引用
对象的自我拯救-二次标记
finalize方法,回收方法区
永久代主要回收两类对象:废弃常量和无用的类。
废弃常量好理解,没有任何对象引用常量池中的某个变量,这个变量就是废弃常量。
如何判断一个类是无用的类
标记-清除算法
当对象被标记为辣鸡后,直接清理掉。
效率不高、容易产生内存碎片
标记-整理算法
被标记为辣鸡的对象回收之后,整理内存空间。
复制算法
将内存分为大小相等的两块,每次内存分配的时候只使用其中的一块,当这块内存满了只有,将存活对象复制到另一块内存空间中,然后整块清理。
实现简单、运行高效
但是浪费一半的内存。
分代收集算法
目前使用这种算法。
新生代中发生GC -- minor gc
minor GC test
public class HeapTest {
private byte[] bytes = new byte[1024*100];
public static void main(String[] args) throws InterruptedException {
List<HeapTest> list = new ArrayList<>();
while (true) {
System.out.println(111);
list.add(new HeapTest());
Thread.sleep(10);
}
}
}

这图是上面的代码运行时的gc情况。

从图中可以得出结论,新生成的对象都是在Eden区,当Eden区满了后,会执行gc回收,将Eden区与S0区中的存活对象拷贝到S1,并清空Eden、S0,存活对象年龄+1;
当新生对象又一次将Eden区填满后,会将Eden区、S1中的存活对象拷贝到S0,并清空S1,存活对象年龄+1;
当存活对象的年龄达到15后,会被认为是老不死对象,挪到老年代内存中。
新生代中的GC 叫做minor GC。
老年代内存占满后进行的GC就是FULL GC。
minor GC正常情况下可以回收70--95%的空间。
对象进入老年代的情况:
JVM调优的目的:减少FULL GC

-XX:+UseParallelGC
TODO
JVM调优参数
JDK工具
安全点与安全区域
STW
各种垃圾收集器
逃逸分析与标量替换

Copyright © 2015 Powered by MWeb, Theme used GitHub CSS.