JVM内存最大能调多大分析【经典】

上次用weblogic 把 -XmxXXXX 设成2G,就启动不起来,设小点就起来了,当时很气,怎么2G都起不了,今天在看到了一篇解释,转过来了
这 次一位老友提出了这个问题,记得当年一个java高手在blogjava提出后,被骂得半死。你们使用java -XmxXXXX -version版本得出了不一样的结论。后来老友说大概是1800M左右,我当时反驳,“我设置过服务器8G内存,我使用两个tomcat,每一个2G”。 为此,我翻开全部的JVM的内存管理的c代码,没有任何结论。我不是linux内核程序员,可是我看过linux的源码,知道32位体系结构的计算机寻址 空间是2^32=4G,intel Pentium Pro处理器寻址空间是36位,CPU内部增长了PAE寄存器。用于处理多出来的4根地址
线 的使用,因此PAE的技术实现最大2^36=64G寻址。经过linux的内核源码,标准Linux内核对于物理内存的管理采用1:3的分配比例,即物理 内存的1/4为内核空间(kernel space),剩下的3/4为用户进程空间(user space),所以,在一台4G内存的服务器上,用户进程可以使用的内存最大也就是3G。当进程被内核调入CPU运行时,不一样的地址空间数据会被调入4G以 内的用户进程空间,其实就能用3G。 IA32架构上,单一进程是不能使用超过4G的内存空间的。可是我记得我给mysql server分配内存大约是1.7G左右,不是2的32次方-1,我分配java 2G内存的计算机是IBM的RS6000.
通过不一样平台的测 试,我得出了大概的数值,win2k下1.6G左右,nt下1.2G,缘由是这样的,Classic VM and HotSpot VM 存放用户区的连续地址中,NT把 kernel DLLs 放在 0x7c 开头的地址空间,因此nt下只有<2G的空间,因此JVM heap 使用极限是2G.用户的dll开始于0x77000000,用户的应用程序开始于0x00400000.我如今惟一肯定的是sun可能为了防止和某些 JVM插件的冲突,把dll的地址给rebase一下,这样使用的空间就不多了一部分.为什末rebase,缘由是这样的,由于在windows下编译 dll 的默认地址都是10000000, 通常在release以前的时候要rebase一下,rebase 的 -b 这个参数是指定一个起始地址,MSDN建议地址是0x60000000,这个工具随visual studio和platform SDK发放。
例 如
rebase.exe -b 0x6D000000 /jdk/jre/bin/*.dll /jdk/jre/bin/hotspot/jvm.dll这样你的JVM用的内存多一些,目前关于这个我只能获得BEA的 JRockit最大也只能使用1.8G内存,看来各家编译JDK时都做了些手脚.
目前只能获得bea的的-Xmx最小值是16 MB,sun的资料很不全,还好java开源了,能够不依靠sun了.java

sun提供的资料
Maximum Address Space Per Process  
mysql

Operating System                   Maximum Address Space Per Processlinux

Redhat Linux 32 bit                                      2 GB程序员

Redhat Linux  64 bit                                     3 GBweb

Windows 98/2000/NT/Me/XP                                  2 GBsql

Solaris x86 (32 bit)                                      4 GB编程

Solaris 32 bit                                            4 GBwindows

Solaris 64 bit                                            Terabytes
以 上文档有误,32位的redhat Server利用 Highmem技术可使用3G内存.
solaris不愧是java的诞平生台。
tomcat

问了一下bea的工程师,得出大体的结论,
Windows 2003/XP using the /3GB switch (32-bit OS)
1.85 GB - JRockit 5.0 R25.2 (SP2)
2.85 GB - JRockit 5.0 R26 (SP3)
服务器

Windows 2003/XP x64 Edition with a 32-bit JVM (64-bit OS)
2.05 GB - JRockit 5.0 R25.2 (SP2)
3.85 GB - JRockit 5.0 R26 (SP3)

对于windows 2000打开3G模式,windows核心编程说得很清楚,boot.ini加入/3G参数。

[boot loader]
timeout=30
default=multi(0)disk(0)rdisk(0)partition(2)/WINNT
[operating systems]
multi(0)disk(0)rdisk(0)partition(2)/WINNT="????" /3GB

Note: "????" in the previous example can be the programmatic name of any of the following operating system versions:

Windows XP Professional
Windows Server 2003
Windows Server 2003, Enterprise Edition
Windows Server 2003, Datacenter Edition
Windows 2000 Advanced Server
Windows 2000 Datacenter Server
Windows NT Server 4.0, Enterprise Edition

在个人机子测试一把,个人本身配置,1G内存,winXP

没有打开3G模式,sun的jdk 1.6 java -Xmx1447M -version,揪出错了,jrockit-R27.1.0-jdk1.5.0_08为1911M,3G模式 sun的jdk没有变化,IBM J9 VM (build 2.3, J2RE 1.5.0 IBM J9 2.3 Windows XP x86-32 j9vmwi3223-2006050
4 (JIT enabled) 3G和2G相同,java -Xmx1787M -version 就出问题,jrockit-R27.1.0-jdk1.5.0_08为2899M,注意Xmx的内存不是物 理内存,个人机子物理内存只有1G
jrockit不愧为java第一虚拟机,只惋惜不开源。




今天分析了当前比较流行的几个不一样公司不一样版本JVM的最大内存,得出来的结果以下: 

公司 JVM版本 最大内存(兆)client 最大内存(兆)server 
SUN 1.5.x 1492 1520 
SUN 1.5.5(Linux) 2634 2660 
SUN 1.4.2 1564 1564 
SUN 1.4.2(Linux) 1900 1260 
IBM 1.4.2(Linux) 2047 N/A 
BEA JRockit 1.5 (U3) 1909 1902 



除非特别说明,不然JVM版本都运行在Windows操做系统下 

附:如何得到JVM的最大可用内存 

在命令行下用 java -Xmx1200m -XX:MaxPermSize=60m -version 命令来进行测试,而后逐渐的增大XXXX的值,若是执行正常就表示指定的内存大小可用,不然会打印错误信息。
最后获得的虚拟机实际分配到的 
总内存大小=堆内存+非堆内存
1200m:为堆内存大小,若是不指定后者参数则有最大数限制,网上不少文章认为这就是JVM内存,-Xmx为设置最大堆内存
60m:
为非堆内存大小,-XX:MaxPermSize实为永久域内存,在堆内存以外,属于非堆内存部分,jdk1.5我测了好像默认为62m,即获得非堆部分默认内存)

Sun HotSpot 1.4.1使用分代收集器,它把堆分为三个主要的域:新域、旧域以及永久域。Sun JVM生成的全部新对象放在新域中。一旦对象经历了必定数量的垃圾收集循环后,便得到使用期并进入旧域。在永久域中Sun JVM则存储class和method对象。就配置而言,永久域是一个独立域而且不认为是堆的一部分。

实际发现版本上有细微差异的JDK最大允许内存值都不尽相同,所以在实际的应用中仍是要本身试验一下看到底内存能达到什么样的值。 

经过这个表想说明的是,若是你的机器的内存太多的话,只能经过多运行几个实例来提供机器的利用率了,例如跑Tomcat,你能够多装几 个Tomcat并 作集群,依此类推。 

≡≡≡ 网友评论 ≡≡≡ 
东子 网友说: 
Windows下的最大内存应该跟NT内核对地址空间的保留也有关系, 好像默认状况下NT内核要占用高2G的地址空间, 因此应用程序撑死能得到的内存不会超过2G; 记得有一个参数可让NT只占1G内存, 这样应用程序就有3G地址空间可用, 相应环境下JVM能容许的最大内存可能也会升高. 

at 05-10-06 00:04 
purpureleaf 网友说: 
windows的每一个应用(不是寻址)的寻址空间通常是2g或者3g,取决于一个参数。可是只要使用一组特定的函数分配内存,每一个应用的寻址空间能够远远 超过4g 

jdk多是设置不了那个大的内存,但那不是windows形成的,是jdk形成的,在linux上同样设置不了。看来作java的朋友对windows 仍是不熟

相关文章
相关标签/搜索