vm options配置
-XX:+UseSerialGC -verbose:gc -Xms20m -Xmx20m -Xmn10m -XX:SurvivorRatio=8 -XX:+PrintGCDetails
解释:
- java堆的大小为20m,不可扩展。
- 其中10m分配给新生代,剩下的分配给老年代。
- -XX:+PrintGCDetails 决定新生代中Eden区域一个Survivor区的空间比率为8:1,也就是Eden占8m,From占1m,to占1m。
设置JDK1.7的条件下运行
// An highlighted block
Heap
PSYoungGen total 9216K, used 2170K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
eden space 8192K, 26% used [0x00000000ff600000,0x00000000ff81e960,0x00000000ffe00000)
from space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
to space 1024K, 0% used [0x00000000ffe00000,0x00000000ffe00000,0x00000000fff00000)
ParOldGen total 10240K, used 0K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)
object space 10240K, 0% used [0x00000000fec00000,0x00000000fec00000,0x00000000ff600000)
PSPermGen total 21504K, used 2998K [0x00000000f9a00000, 0x00000000faf00000, 0x00000000fec00000)
object space 21504K, 13% used [0x00000000f9a00000,0x00000000f9cedae8,0x00000000faf00000)
Process finished with exit code 0
设置JDK1.8的条件下运行
// An highlighted block
Heap
PSYoungGen total 9216K, used 2850K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
eden space 8192K, 34% used [0x00000000ff600000,0x00000000ff8c8a58,0x00000000ffe00000)
from space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
to space 1024K, 0% used [0x00000000ffe00000,0x00000000ffe00000,0x00000000fff00000)
ParOldGen total 10240K, used 0K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)
object space 10240K, 0% used [0x00000000fec00000,0x00000000fec00000,0x00000000ff600000)
Metaspace used 3424K, capacity 4496K, committed 4864K, reserved 1056768K
class space used 380K, capacity 388K, committed 512K, reserved 1048576K
Process finished with exit code 0
比较说明
1、JDK1.8开始,元空间替换持久代。取消的原因如下:
- 它的大小是在启动时固定好的——很难进行调优。-XX:MaxPermSize,设置成多少好呢?
- HotSpot的内部类型也是Java对象:它可能会在Full GC中被移动,同时它对应用不透明,且是非强类型的,难以跟踪调试,还需要存储元数据的元数据信息(meta-metadata)。
- 简化Full GC:每一个回收器有专门的元数据迭代器。
- 可以在GC不进行暂停的情况下并发地释放类数据。
- 使得原来受限于持久代的一些改进未来有可能实现
2、根据上面的各种原因,永久代最终被移除,方法区移至Metaspace,字符串常量移至Java Heap。移除持久代后,PermGen空间的状况:
- 这部分内存空间将全部移除。
- JVM的参数:PermSize 和 MaxPermSize 会被忽略并给出警告(如果在启用时设置了这两个参数)。
- 随着JDK8的到来,JVM不再有PermGen。但类的元数据信息(metadata)还在,只不过不再是存储在连续的堆空间上,而是移动到叫做“Metaspace”的本地内存(Native memory)中。
JDK内存模型对比
1.7构成
1.8的构成
垃圾收集器的指定
- 串行收集器 DefNew:是使用-XX:+UseSerialGC (新生代,老年代都使用串行回收收集器)。
- 并行收集器 ParNew:是使用-XX:+UseParNewGC (新生代使用并行收集器,老年代使用串行回收收集器)
或者-XX:+UseConcMarkSweepGC(新生代使用并行收集器,老年代使用CMS)。 - PSYoungGen: 是使用-XX:+UseParallelOldGC (新生代,老年代都使用并行回收收集器)
或者-XX:+UseParallelGC (新生代使用并行回收收集器,老年代使用串行收集器) - garbage-first heap: 是使用-XX:+UseG1GC (G1收集器)
代码测试
private static final int _1MB = 1024*1024;
// 运行一下方法,会进行一次垃圾回收
public static void testAllocation() {
byte[] allocation1,allocation2,allocation3,allocation4;
allocation1 = new byte[2*_1MB];
allocation2 = new byte[2*_1MB];
allocation3 = new byte[2*_1MB];
allocation4 = new byte[4*_1MB];
}
结果
[GC (Allocation Failure) [DefNew: 6618K->743K(9216K), 0.0055895 secs] 6618K->4839K(19456K), 0.0056555 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
Heap
def new generation total 9216K, used 7209K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)
eden space 8192K, 78% used [0x00000000fec00000, 0x00000000ff2507a8, 0x00000000ff400000)
from space 1024K, 72% used [0x00000000ff500000, 0x00000000ff5b9dd0, 0x00000000ff600000)
to space 1024K, 0% used [0x00000000ff400000, 0x00000000ff400000, 0x00000000ff500000)
tenured generation total 10240K, used 4096K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
the space 10240K, 40% used [0x00000000ff600000, 0x00000000ffa00020, 0x00000000ffa00200, 0x0000000100000000)
Metaspace used 3473K, capacity 4500K, committed 4864K, reserved 1056768K
class space used 382K, capacity 388K, committed 512K, reserved 1048576K
Process finished with exit code 0
解释:
- GC:代表本次GC是Minor GC,即小型GC。不是Full GC。
- (Allocation Failure):这次垃圾回收是因为“(Allocation Failure)”而导致的。
- [DefNew: 6618K->743K(9216K), 0.0055895 secs] :回收之前年轻代使用6618K,回收之后年轻代使用743K,年轻代内存共计(9216K)。其中,DefNew表示本次使用的是DefNew垃圾回收器。这是由运行参数-XX:+UseSerialGC而指定。如果不指定,缺省是采用的PSYongGen垃圾回收器,以下截图为JDK8的缺省运行结果,以示对比:
- 6618K->4839K(19456K) 回收之前和之后整个堆内存的使用量(整个堆内存大小)