(转载:http://www.javaeye.com/topic/368213 )
接触到的一些用户反映在Linux系统中运行的Java应用,内存只能使用到2GB,在Java虚拟机中如果把-Xmx参数设置到2GB左右(约1.5-1.8GB),java进程就根本启动不了。我们通常使用的JVM都是32位的(64位的JVM会损失10-20%的性能,通常不建议使用),而32位程序的寻址空间应该是4GB才对,为什么Linux上的JVM只能使用2GB的内存呢? (注:Windows上也有类似的问题)
经过和JDK研发组的人员沟通,终于弄清楚了一些相关的原因。这个问题存在于早期的一些Linux版本中,特别是内核2.5以前的版本,2.6以后的版本就基本上没有这个问题了。原来这些Linux版本多是32位的,内核使用了2GB空间,应用进程就只有2GB了,也就是说一个地址连续的内存块大小的上限是2GB,而JVM的堆空间(heap size)需要连续的地址空间,因此,2GB就是java进程的理论使用的内存上限。
如果java应用需要使用较大的内存,建议使用较新版本的linux,或者修改Linux的应用/内核内存比配置为3GB:1GB。还有就是选择如Solaris等的UNIX操作系统。象Solaris这样的操作系统,在内存管理上没有2GB的限制,因此可以把heap size设置到3.5-3.6GB左右。

(1)young generation
年轻代分三个区。一个Eden区,两个Survivor区。大部分对象在 Eden区中生成。当Eden区满时,还存活的对象将被复制到Survivor区(两个中的一个),当这个Survivor区满时,此区的存活对象将被复制到另外一个Survivor区,当这个Survivor区也满了的时候,从第一个Survivor区复制过来的并且此时还存活的对象,将被复制到tenured generation。需要注意,Survivor的两个区是对称的,没先后关系,所以同一个区中可能同时存在从Eden复制过来对象,和从前一个Survivor复制过来的对象,而复制到年老区的只有从第一个Survivor去过来的对象。而且,Survivor区总有一个是空的。
young generation的gc称为minor gc。经过数次minor gc,依旧存活的对象,将被移出young generation,移到tenured generation
(2)tenured generation
生命周期较长的对象,归入到tenured generation。一般是经过多次minor gc,还 依旧存活的对象,将移入到tenured generation。(当然,在minor gc中如果存活的对象的超过survivor的容量,放不下的对象会直接移入到tenured generation)
tenured generation的gc称为major gc,就是通常说的full gc。
采用compaction算法。由于tenured generaion区域比较大,而且通常对象生命周期都比较长,compaction需要一定时间。所以这部分的gc时间比较长。
minor gc可能引发full gc。当eden+from space的空间大于tenured generation区的剩余空间时,会引发full gc。这是悲观算法,要确保eden+from space的对象如果都存活,必须有足够的tenured generation空间存放这些对象。
(3)permanent generation
该区域比较稳定,主要用于存放classloader信息,比如类信息和method信息。
对于spring hibernate这些需要动态类型支持的框架,这个区域需要足够的空间。(这部分空间应该存在于方法区而不是heap中)。