JVM-GC
https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-2.html#jvms-2.5.4
https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html#jvms-2.5.4
运行时数据区
The pc Register
Java Virtual Machine Stacks
Heap
Method Area
Run-Time Constant Pool
Native Method Stacks
一次运行:
public class JustTest {
public static MapSTATIC = new HashMap();
public static void main(String[] args) {
for(int i=0; i< Integer.MAX_VALUE; i++) {
try {
String key = i + "_" +UUID.randomUUID().toString();
String value = UUID.randomUUID().toString();
STATIC.put(key, value);
Thread.sleep(1L);
System.out.println(key + " ====== " + " " + value);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
参数:
-Xms32m
-Xmx256m
结果:
区域 初始值 最大值
Eden 8.5 68.312
S0 1.062 8.5
S1 1.062 8.5
Old 21.375 170.688
Perm 20.750 82
Young = Eden + Survivor(S0 + S1) = 10.624
Old = Old = 21.375
Heap = Young + Old =32M
其中,大概可以看出默认比例:Eden:S0:S1 = 8:1:1,Young : Old = 1 : 2
可以通过 -XX:SurvivorRatio=8 -> Eden : S0/S1 = 8:1, -XX:NewRatio=2 -> Old : Young(New)=2 ,
从这里也可以看出,Perm(永久代)不属于Heap
再提一下永久代和方法区的概念,方法区是一个逻辑概念。而Hotspot虚拟机是通过Perm Gen来实现的,并且Perm Gen是Hotspot特有的概念,并且在jdk 8中已经移除。
从下图中可以看出,内存分配和GC的一些过程:
详细过程见:GC Detail
详细的前二次GC:
1、初始内存分配到Eden
此时,S0、S1、Old 内存都为0
2、Eden空间逐渐占满,触发GC1,回收之后将Eden中存活的对象复制到S1,S1存放不下的,则进入Old。
此时,S1 1.062全部使用,还有583.133K 进入Old
3、GC1之后,Enden被清空,内存依旧分配到Enden,至Enden再次占满
4、触发GC2,将Eden和S1中还存活的对象复制到S0,其他存放不下的对象直接进入Old
此时,S0 958.218K,Old 1.672M,相比上次,又新进入了一些对象
5、重复
注意:内存直接分配到Eden,而不会直接分配到Survivor(SO/S1)。
当Eden占满时,将存活的对象复制到其中一个空的Survivor区域。
GC调优案例:
https://tech.meituan.com/jvm_optimize.html
http://blogxin.cn/2015/12/02/FullGC-frequently/