我在我的 eclipse 中进行开发进行 JVM 参数测试,但是打印出来的 gc 信息和我预想(从书上看)的不一样,找了很多答案也不知道为什么,求大神指点呀!
public class OutOfMemoryTest {
@Test
public void heapOutOfMemory() throws InterruptedException {
//-Xmx4M -Xms4M -Xmn2M -XX:+PrintGCDetails
//Thread.sleep(40000);
byte[] b = new byte[2*1024*1024];
}
}
按照道理来说我设置堆得大小为 4M ,且不可扩展, young 区的大小为 2M ,那么 old 区的大小也应该为 2M,但是为什么 eclipse 中打印出来的 gc 信息是这样的?
Heap
PSYoungGen total 1536K, used 745K [0x00000000ffe00000, 0x0000000100000000, 0x0000000100000000)
eden space 1024K, 25% used [0x00000000ffe00000,0x00000000ffe40628,0x00000000fff00000)
from space 512K, 95% used [0x00000000fff80000,0x00000000ffffa020,0x0000000100000000)
to space 512K, 0% used [0x00000000fff00000,0x00000000fff00000,0x00000000fff80000)
ParOldGen total 4608K, used 2993K [0x00000000ff800000, 0x00000000ffc80000, 0x00000000ffe00000)
object space 4608K, 64% used [0x00000000ff800000,0x00000000ffaec558,0x00000000ffc80000)
PSPermGen total 262144K, used 5380K [0x00000000ef800000, 0x00000000ff800000, 0x00000000ff800000)
object space 262144K, 2% used [0x00000000ef800000,0x00000000efd41350,0x00000000ff800000)
我用 jmap 打印出来的结果也是这样, old 区的大小已经大于我整个堆得大小了? 然后我将代码修改成了这样
@Test
public void heapOutOfMemory() throws InterruptedException {
//-Xmx64M -Xms64M -Xmn32M -XX:+PrintGCDetails
byte[] b = new byte[32*1024*1024];
}
打印出来的信息就正确了, old 区的大小就是 32M 了。打印结果如下:
Heap
PSYoungGen total 28672K, used 1966K [0x00000000fe000000, 0x0000000100000000, 0x0000000100000000)
eden space 24576K, 8% used [0x00000000fe000000,0x00000000fe1eb9c0,0x00000000ff800000)
from space 4096K, 0% used [0x00000000ff800000,0x00000000ff800000,0x00000000ffc00000)
to space 4096K, 0% used [0x00000000ffc00000,0x00000000ffc00000,0x0000000100000000)
ParOldGen total 32768K, used 1292K [0x00000000fc000000, 0x00000000fe000000, 0x00000000fe000000)
object space 32768K, 3% used [0x00000000fc000000,0x00000000fc1432e8,0x00000000fe000000)
PSPermGen total 262144K, used 5421K [0x00000000ec000000, 0x00000000fc000000, 0x00000000fc000000)
object space 262144K, 2% used [0x00000000ec000000,0x00000000ec54b678,0x00000000fc000000)
但是我还是有一个疑问:为什么 eden:from 的比例不是 8 : 1. 我看了 jvm 虚拟机规范没有发现哪里有对这种情况的说明,是我做的方法不对,理解不对还是怎样的,求大家帮忙解答下。
1
thinkmore OP 使用的系统是 win64 位企业版、 jdk1.7.0_55 、 Luna Service Release 2 (4.4.2)。
|
2
thinkmore OP @SoloCompany 给看下,我的哥
|
3
SoloCompany 2016-10-21 23:53:09 +08:00 1
擦,为啥我会被艾特到的
第一反应,你为啥不查一下是不是 jvm 实现限制了 heap 的下限呢 第二,如果文档没说到,那就只能找源码区确认了, jvm 7 的实现应该是和 openjdk 的实现基本上一致吧 |
4
SoloCompany 2016-10-22 00:05:48 +08:00
其实也不用去确认,你没有看到 OutOfMemoryError 就足够说明问题了,配置根本就被忽略了
我在 java8 下执行的结果并不存在你说的现象 java -Xmx4M -Xms4M -Xmn2M -XX:+PrintGCDetails -cp /private/var/folders/vv/ff28c0z560n407mjb5_x4c9h0000gn/T/CodeRunner Untitled [GC (Allocation Failure) [PSYoungGen: 672K->496K(1536K)] 672K->512K(3584K), 0.0022537 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] [GC (Allocation Failure) [PSYoungGen: 496K->480K(1536K)] 512K->496K(3584K), 0.0007598 secs] [Times: user=0.01 sys=0.01, real=0.00 secs] [Full GC (Allocation Failure) [PSYoungGen: 480K->0K(1536K)] [ParOldGen: 16K->428K(2048K)] 496K->428K(3584K), [Metaspace: 2727K->2727K(1056768K)], 0.0062196 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] [GC (Allocation Failure) [PSYoungGen: 0K->0K(1536K)] 428K->428K(3584K), 0.0005307 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] [Full GC (Allocation Failure) [PSYoungGen: 0K->0K(1536K)] [ParOldGen: 428K->417K(2048K)] 428K->417K(3584K), [Metaspace: 2727K->2727K(1056768K)], 0.0042598 secs] [Times: user=0.01 sys=0.00, real=0.01 secs] Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at Untitled.main(Untitled 3.java:3) Heap PSYoungGen total 1536K, used 30K [0x00000007bfe00000, 0x00000007c0000000, 0x00000007c0000000) eden space 1024K, 2% used [0x00000007bfe00000,0x00000007bfe07890,0x00000007bff00000) from space 512K, 0% used [0x00000007bff00000,0x00000007bff00000,0x00000007bff80000) to space 512K, 0% used [0x00000007bff80000,0x00000007bff80000,0x00000007c0000000) ParOldGen total 2048K, used 417K [0x00000007bfc00000, 0x00000007bfe00000, 0x00000007bfe00000) object space 2048K, 20% used [0x00000007bfc00000,0x00000007bfc685d0,0x00000007bfe00000) Metaspace used 2759K, capacity 4486K, committed 4864K, reserved 1056768K class space used 300K, capacity 386K, committed 512K, reserved 1048576K |
5
thinkmore OP @SoloCompany 谢谢。
关于你说的两个方法 1. 我没有找到任何资料关于这个下限的设置 2. 源码确认你说的是 C++实现的代码吗?如果是这个,个人能力有限,看不太懂 c++代码。 还有 @你,是因为我觉得你牛。 再次感谢 |
6
thinkmore OP @SoloCompany jdk8 中应该有很多变化,方法区都变化了。
|
7
SoloCompany 2016-10-22 20:03:48 +08:00
@thinkmore java7 运行的结果, map 显示的很清楚啊,显然你配置成 4MB 的 heap 是无效的,被自动调整为 8MB
$JAVA7_HOME/bin/jmap -heap 95786 Attaching to process ID 95786, please wait... Debugger attached successfully. Server compiler detected. JVM version is 24.79-b02 using thread-local object allocation. Parallel GC with 4 thread(s) Heap Configuration: MinHeapFreeRatio = 0 MaxHeapFreeRatio = 100 MaxHeapSize = 8388608 (8.0MB) NewSize = 2097152 (2.0MB) MaxNewSize = 2097152 (2.0MB) OldSize = 5439488 (5.1875MB) NewRatio = 2 SurvivorRatio = 8 PermSize = 21757952 (20.75MB) MaxPermSize = 85983232 (82.0MB) G1HeapRegionSize = 0 (0.0MB) … ... |
8
thinkmore OP @SoloCompany 我用 jmap 打印出来确实是调整了,但是为什么会被动态调整呢?
今天我查阅了 oracle 的官方资料,上面只说了 Parallel Scavenge(64 位系统 server 模式下的默认收集器)因为默认开启了 UseAdaptiveSizePolicy 参数,所以才会对新生代的大小进行动态调整,但是为啥我使用其他收集器测试正如 jmap 中打印出来的参数那样 maxHeapSize 被修改成了 8M,我设置的 4M 没起作用。我使用这样的参数进行模拟: ``` //-Xmx6M -Xms6M -XX:+PrintGCDetails -XX:-UseAdaptiveSizePolicy -XX:+UseParNewGC Heap Configuration: MinHeapFreeRatio = 40 MaxHeapFreeRatio = 70 MaxHeapSize = 8388608 (8.0MB) NewSize = 1310720 (1.25MB) MaxNewSize = 17592186044415 MB OldSize = 5439488 (5.1875MB) NewRatio = 2 SurvivorRatio = 8 PermSize = 21757952 (20.75MB) MaxPermSize = 85983232 (82.0MB) G1HeapRegionSize = 0 (0.0MB) Heap Usage: New Generation (Eden + 1 Survivor Space): capacity = 1900544 (1.8125MB) used = 693800 (0.6616592407226562MB) free = 1206744 (1.1508407592773438MB) 36.50533741918103% used Eden Space: capacity = 1703936 (1.625MB) used = 497192 (0.47415924072265625MB) free = 1206744 (1.1508407592773438MB) 29.179030198317307% used From Space: capacity = 196608 (0.1875MB) used = 196608 (0.1875MB) free = 0 (0.0MB) 100.0% used To Space: capacity = 196608 (0.1875MB) used = 0 (0.0MB) free = 196608 (0.1875MB) 0.0% used tenured generation: capacity = 4194304 (4.0MB) used = 1415024 (1.3494720458984375MB) free = 2779280 (2.6505279541015625MB) 33.73680114746094% used Perm Generation: capacity = 21757952 (20.75MB) used = 5838448 (5.5679779052734375MB) free = 15919504 (15.182022094726562MB) 26.833628459149097% used ``` 而且 eden:from 的比例也不是 8:1 呀! 参考文档:http://www.oracle.com/technetwork/java/javase/gc-tuning-6-140523.html 哥,如果可以的话,加个 q 吧。 353003874 |
9
SoloCompany 2016-10-23 01:00:04 +08:00 1
|
10
thinkmore OP @SoloCompany 谢谢,找到原因了!
|