您的位置:首页 > 编程语言 > Java开发

Java OutOfMemory Error引发的JVM参数实测--Xms和Xmx参数篇

2013-05-26 19:22 316 查看
此篇文章是接上一篇博客“Java OutOfMemory Error引发的JVM参数实测--线程堆栈参数篇”的后续测试。

测试目的:

通过Sun  Java 1.6.0_20 32bit 版本运行上篇博客中的Java程序,测试在不同的线程堆栈参数设置的情况下分别可以生成多少个线程。

测试一:

使用默认的Java Xms和Xmx设置,测试生成的Java线程数:

./jre1.6.0_20/bin/java -server TestNativeOutOfMemoryError

..........................

I = 9141

i = 9142

i = 9143

i = 9144

Exception in thread "main" java.lang.OutOfMemoryError: unable to create new native thread

        at java.lang.Thread.start0(Native Method)

        at java.lang.Thread.start(Unknown Source)

        at TestNativeOutOfMemoryError.main(TestNativeOutOfMemoryError.java:9)

Java HotSpot(TM) Server VM warning: Exception java.lang.OutOfMemoryError occurred dispatching signal SIGINT to handler- the VM may need to be forcibly terminated

运行java 程序之前,系统可用内存:

[root@tivbsmv999 ~]# free -m

             total       used       free     shared    buffers     cached

Mem:          3949       2324       1625          0          8       1704

-/+ buffers/cache:        610       3339

Swap:         5951         11       5940

运行java 程序之后,系统可用内存:

[root@tivbsmv999 ~]# free -m

             total       used       free     shared    buffers     cached

Mem:          3949       2702       1246          0          9       1705

-/+ buffers/cache:        987       2961

Swap:         5951         11       5940

内存消耗量 = 1625 - 1246 = 379 Mb

测试二:

将Java Xms和Xmx设置为512m,测试生成的Java线程数:

./jre1.6.0_20/bin/java -server -Xms500m -Xmx500m TestNativeOutOfMemoryError

..........................

i = 10652

i = 10653

i = 10654

i = 10655

Exception in thread "main" java.lang.OutOfMemoryError: unable to create new native thread

        at java.lang.Thread.start0(Native Method)

        at java.lang.Thread.start(Unknown Source)

        at TestNativeOutOfMemoryError.main(TestNativeOutOfMemoryError.java:9)

运行java 程序之前,系统可用内存:

[root@tivbsmv999 ~]# free -m

             total       used       free     shared    buffers     cached

Mem:          3949       2326       1623          0          9       1705

-/+ buffers/cache:        611       3338

Swap:         5951         11       5940

运行java 程序之后,系统可用内存:

[root@tivbsmv999 ~]# free -m

             total       used       free     shared    buffers     cached

Mem:          3949       2776       1173          0         10       1705

-/+ buffers/cache:       1060       2889

Swap:         5951         11       5940

内存消耗量 = 1623 - 1173 = 450 Mb

测试三:

将Java Xms和Xmx设置为1024m,测试生成的Java线程数:

./jre1.6.0_20/bin/java -server -Xms1024m -Xmx1024m TestNativeOutOfMemoryError

..........................

i = 9031

i = 9032

i = 9033

i = 9034

Exception in thread "main" java.lang.OutOfMemoryError: unable to create new native thread

        at java.lang.Thread.start0(Native Method)

        at java.lang.Thread.start(Unknown Source)

        at TestNativeOutOfMemoryError.main(TestNativeOutOfMemoryError.java:9)

运行java 程序之前,系统可用内存:

[root@tivbsmv999 ~]# free -m

             total       used       free     shared    buffers     cached

Mem:          3949       2328       1621          0         10       1705

-/+ buffers/cache:        612       3337

Swap:         5951         11       5940

运行java 程序之后,系统可用内存:

[root@tivbsmv999 ~]# free -m

             total       used       free     shared    buffers     cached

Mem:          3949       2714       1235          0         10       1705

-/+ buffers/cache:        997       2952

Swap:         5951         11       5940

内存消耗量 = 1621 - 1235 = 386 Mb

测试四:

将Java Xms和Xmx设置为2000m,测试生成的Java线程数:

./jre1.6.0_20/bin/java -server -Xms2000m -Xmx2000m TestNativeOutOfMemoryError

..........................

i = 6009

i = 6010

i = 6011

i = 6012

Exception in thread "main" java.lang.OutOfMemoryError: unable to create new native thread

        at java.lang.Thread.start0(Native Method)

        at java.lang.Thread.start(Unknown Source)

        at TestNativeOutOfMemoryError.main(TestNativeOutOfMemoryError.java:9)

运行java 程序之前,系统可用内存:

[root@tivbsmv999 ~]# free -m

             total       used       free     shared    buffers     cached

Mem:          3949       2313       1635          0          8       1695

-/+ buffers/cache:        609       3339

Swap:         5951         11       5940

运行java 程序之后,系统可用内存:

[root@tivbsmv999 ~]# free -m

             total       used       free     shared    buffers     cached

Mem:          3949       2606       1343          0          9       1711

-/+ buffers/cache:        885       3063

Swap:         5951         11       5940

内存消耗量 = 1635 - 1343 = 292 Mb

测试五:

将Java Xms和Xmx设置为2400m,测试生成的Java线程数:

./jre1.6.0_20/bin/java -server -Xms2400m
4000
-Xmx2400m TestNativeOutOfMemoryError

..........................

i = 4770

i = 4771

i = 4772

i = 4773

Exception in thread "main" java.lang.OutOfMemoryError: unable to create new native thread

        at java.lang.Thread.start0(Native Method)

        at java.lang.Thread.start(Unknown Source)

        at TestNativeOutOfMemoryError.main(TestNativeOutOfMemoryError.java:9)

运行java 程序之前,系统可用内存:

[root@tivbsmv999 ~]# free -m

             total       used       free     shared    buffers     cached

Mem:          3949       2381       1568          0          9       1761

-/+ buffers/cache:        610       3339

Swap:         5951         11       5940

运行java 程序之后,系统可用内存:

[root@tivbsmv999 ~]# free -m

             total       used       free     shared    buffers     cached

Mem:          3949       2584       1365          0         10       1761

-/+ buffers/cache:        813       3136

Swap:         5951         11       5940

内存消耗量 = 1568 - 1365 = 203 Mb

测试六:

将Java Xms和Xmx设置为256m,测试生成的Java线程数:

./jre1.6.0_20/bin/java -server -Xms256m -Xmx256m TestNativeOutOfMemoryError

..........................

i = 11409

i = 11410

i = 11411

i = 11412

Exception in thread "main" java.lang.OutOfMemoryError: unable to create new native thread

        at java.lang.Thread.start0(Native Method)

        at java.lang.Thread.start(Unknown Source)

        at TestNativeOutOfMemoryError.main(TestNativeOutOfMemoryError.java:9)

运行java 程序之前,系统可用内存:

[root@tivbsmv999 ~]# free -m

             total       used       free     shared    buffers     cached

Mem:          3949       2381       1567          0         10       1761

-/+ buffers/cache:        610       3339

Swap:         5951         11       5940

运行java 程序之后,系统可用内存:

[root@tivbsmv999 ~]# free -m

             total       used       free     shared    buffers     cached

Mem:          3949       2851       1098          0         10       1761

-/+ buffers/cache:       1079       2870

Swap:         5951         11       5940

内存消耗量 = 1567 - 1098 = 469 Mb

测试七:

将Java Xms和Xmx设置为128m,测试生成的Java线程数:

./jre1.6.0_20/bin/java -server -Xms128m -Xmx128m TestNativeOutOfMemoryError

..........................

i = 11803

i = 11804

i = 11805

i = 11806

Exception in thread "main" java.lang.OutOfMemoryError: unable to create new native thread

        at java.lang.Thread.start0(Native Method)

        at java.lang.Thread.start(Unknown Source)

        at TestNativeOutOfMemoryError.main(TestNativeOutOfMemoryError.java:9)

运行java 程序之前,系统可用内存:

[root@tivbsmv999 ~]# free -m

             total       used       free     shared    buffers     cached

Mem:          3949       2382       1566          0         10       1761

-/+ buffers/cache:        610       3338

Swap:         5951         11       5940

运行java 程序之后,系统可用内存:

[root@tivbsmv999 ~]# free -m

             total       used       free     shared    buffers     cached

Mem:          3949       2858       1090          0         11       1761

-/+ buffers/cache:       1086       2863

Swap:         5951         11       5940

内存消耗量 = 1566 - 1090 = 476 Mb

测试结果分析:

1. 上述的测试结果纠正了我之前的错误观念,并不是给JVM 堆(Xmx)分配的内存越多,Java进程可以创建的线程就越多,而且恰恰是相反的。上述的测试结果说明给Xmx分配的内存越多,Java可创建的线程数量越少。从网上找了一些文章得知,堆主要是用来存放对象的,栈是用来执行程序的。JVM中的堆内存(Heap)和栈内存(Stack)的作用非别为:

JVM堆中存的是对象。每一个Java应用都唯一对应一个JVM实例,每个JVM实例唯一对应一个堆。Java堆的唯一目的就是存放对象实例,应用程序在运行中所创建的所有对象实例和数组都在这里分配空间,并由所有的线程所共享。Java中堆内存的分配是自动初始化的。Java中所有对象的存储空间都是在堆内存中进行分配的,但是这个对象的引用却是在栈内存中分配的。也就是在建立一个对象时从堆内存和栈内存都分配内存空间。在堆中分配的空间用来实际建立这个对象,而在栈中分配的内存只是指向这个堆对象的引用而已。

JVM栈中存的是基本数据类型和JVM堆中对象的引用。一个对象的大小是不可估计的,或者说是可以动态变化的,但是在JVM栈中,一个对象只对应了一个4btye的引用。基本数据类型占用的空间一般是1~8个字节。JVM栈是程序运行时单位,决定了程序如何运行,或者说数据如何处理。在Java中,没生成一个线程,就会有一个JVM栈与之对应。因为不同的线程的执行逻辑显然是不同的,所以每个线程都需要一个独立的栈空间来存放该线程的执行逻辑。

从上述堆和栈的作用和区别可以看出,Java进程所能创建的线程数量是跟每个线程占用的JVM栈的大小和系统的可用内存密切相关的。其中每个线程占用的JVM栈的大小是通过参数Xss来设定的。在Xss已定的情况下,分配给JVM堆的内存空间越多,系统的可用内存就越少,所以Java进程可创建的线程数量就越少。

2. 在测试一和测试三中,Java可以创建的线程数量差不多,可以推测默认的堆大小也在1G左右,验证了默认堆的最大值(Xmx)为物理内存的1/4的说法。另外看到有文章说默认堆的最小值(Xms)为物理内存的1/64,这里未做验证。

3. 将上述各个测试中Java程序运行前后的内存消耗量除以生成的线程数量,都可以得出每个线程占用的内存数量大约为0.04 Mb。跟上篇博客“Java OutOfMemory Error引发的JVM参数实测--线程堆栈参数篇”中的Xss的默认值320k是基本吻合的。

参考:

JVM内存管理:
http://yuntai.1kapp.com/?p=528
JVM中堆内存和栈内存详解:
http://www.360doc.com/content/12/0306/17/1429048_192252660.shtml
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Java 线程 JVM