Java技术体系动态内存管理也就是给对象分配内存以及回收分配给对象内存;这一点和传统的C/C++技术体系有着很大的区别。本文主要讲述java堆内存分配与回收策略。
下图给出java堆内存结构,其分为两大块区域:新生代、老年代。其中新生代又包含三个区域:一个Eden区和两个Survivor区,由于在发生Minor GC时候会把存活的对象拷贝到另一个Survivor区上,因此也称为from区和to区 。
public class EdenTest {
private static final int _1MB=1024*1024;
/**
* VM -verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails
* @param args
*/
public static void main(String[] args) throws Exception{
//通GC日志可以看到对象优先分配到Eden区域
byte[] bytes=new byte[_1MB*4];
}
}
通过GC 日志可以看出eden区域空间已经有77%使用,from to 区域也就是两个Survivor区域大小没有减少,老年代的空间也没有减少。
Heap
PSYoungGen total 9216K, used 6322K [0x00000007bf600000, 0x00000007c0000000, 0x00000007c0000000)
eden space 8192K, 77% used [0x00000007bf600000,0x00000007bfc2cba0,0x00000007bfe00000)
from space 1024K, 0% used [0x00000007bff00000,0x00000007bff00000,0x00000007c0000000)
to space 1024K, 0% used [0x00000007bfe00000,0x00000007bfe00000,0x00000007bff00000)
ParOldGen total 10240K, used 0K [0x00000007bec00000, 0x00000007bf600000, 0x00000007bf600000)
object space 10240K, 0% used [0x00000007bec00000,0x00000007bec00000,0x00000007bf600000)
Metaspace used 3313K, capacity 4496K, committed 4864K, reserved 1056768K
class space used 369K, capacity 388K, committed 512K, reserved 1048576K
/**
* Created by apple on 17/10/31.
*/
public class EdenTest {
private static final int _1MB = 1024 * 1024;
/**
* -verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:SurvivorRatio=8 -XX:+PrintGCDetails
* -XX:PretenureSizeThreshold=4194304 -XX:+UseSerialGC
*
* @param args
*/
public static void main(String[] args) throws Exception {
//对象直接分配到老年代
byte[] bytes1 = new byte[4*_1MB];
}
}
从GC日志可以看出大对象直接分配到tenured区域(老年代)
Heap
def new generation total 9216K, used 2226K [0x00000007bec00000, 0x00000007bf600000, 0x00000007bf600000)
eden space 8192K, 27% used [0x00000007bec00000, 0x00000007bee2cb90, 0x00000007bf400000)
from space 1024K, 0% used [0x00000007bf400000, 0x00000007bf400000, 0x00000007bf500000)
to space 1024K, 0% used [0x00000007bf500000, 0x00000007bf500000, 0x00000007bf600000)
tenured generation total 10240K, used 4096K [0x00000007bf600000, 0x00000007c0000000, 0x00000007c0000000)
the space 10240K, 40% used [0x00000007bf600000, 0x00000007bfa00010, 0x00000007bfa00200, 0x00000007c0000000)
Metaspace used 3299K, capacity 4496K, committed 4864K, reserved 1056768K
class space used 368K, capacity 388K, committed 512K, reserved 1048576K
public class EdenTest {
private static final int _1MB = 1024 * 1024;
/**
*-verbose:gc -Xms200M -Xmx200M -Xmn100M -XX:SurvivorRatio=8 -XX:+PrintGCDetails -XX:+UseSerialGC
* -XX:MaxTenuringThreshold=1
*
* @param args
*/
public static void main(String[] args) throws Exception {
byte[] bytes1 = new byte[4*_1MB];
byte[] bytes2 = new byte[50 * _1MB];
bytes2 = null;
bytes2 = new byte[50 * _1MB];
bytes2 = null;
bytes2 = new byte[50 * _1MB];
}
}
-XX:MaxTenuringThreshold=1 时候
[GC (Allocation Failure) [DefNew: 60211K->4523K(92160K), 0.0045386 secs] 60211K->4523K(194560K), 0.0045717 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
[GC (Allocation Failure) [DefNew: 55723K->0K(92160K), 0.0037334 secs] 55723K->4511K(194560K), 0.0037593 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
Heap
def new generation total 92160K, used 52019K [0x00000007b3800000, 0x00000007b9c00000, 0x00000007b9c00000)
eden space 81920K, 63% used [0x00000007b3800000, 0x00000007b6acce50, 0x00000007b8800000)
from space 10240K, 0% used [0x00000007b8800000, 0x00000007b8800000, 0x00000007b9200000)
to space 10240K, 0% used [0x00000007b9200000, 0x00000007b9200000, 0x00000007b9c00000)
tenured generation total 102400K, used 4511K [0x00000007b9c00000, 0x00000007c0000000, 0x00000007c0000000)
the space 102400K, 4% used [0x00000007b9c00000, 0x00000007ba067e70, 0x00000007ba068000, 0x00000007c0000000)
Metaspace used 3313K, capacity 4496K, committed 4864K, reserved 1056768K
class space used 369K, capacity 388K, committed 512K, reserved 1048576K
-XX:MaxTenuringThreshold=15 时候
[GC (Allocation Failure) [DefNew: 60211K->4523K(92160K), 0.0043589 secs] 60211K->4523K(194560K), 0.0043856 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
[GC (Allocation Failure) [DefNew: 55723K->4511K(92160K), 0.0045079 secs] 55723K->4511K(194560K), 0.0045374 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
Heap
def new generation total 92160K, used 58169K [0x00000007b3800000, 0x00000007b9c00000, 0x00000007b9c00000)
eden space 81920K, 65% used [0x00000007b3800000, 0x00000007b6c66800, 0x00000007b8800000)
from space 10240K, 44% used [0x00000007b8800000, 0x00000007b8c67e70, 0x00000007b9200000)
to space 10240K, 0% used [0x00000007b9200000, 0x00000007b9200000, 0x00000007b9c00000)
tenured generation total 102400K, used 0K [0x00000007b9c00000, 0x00000007c0000000, 0x00000007c0000000)
the space 102400K, 0% used [0x00000007b9c00000, 0x00000007b9c00000, 0x00000007b9c00200, 0x00000007c0000000)
Metaspace used 3313K, capacity 4496K, committed 4864K, reserved 1056768K
class space used 369K, capacity 388K, committed 512K, reserved 1048576K
GC 触发的条件:
参考文献
[1] 深入理解java 虚拟机(第二版),周志明著