Java Heap分为3个区
1.Young(年轻代)
2.Old(年老代)
3.Permanent(持久代)
Young保存刚实例化的对象。当该区被填满时,GC会将对象移到Old区。
持久区又叫方法区:存放每个Class的结构信息,包括常量池、字段描述、方法描述等等。
JVM有2个GC线程
第一个线程负责回收Heap的Young区
第二个线程在Heap不足时,遍历Heap,将Young 区升级为Older区
-Xms | Java Heap初始值 | 默认是物理内存的1/64 |
-Xmx | Java Heap最大值 | 默认是物理内存的1/4 |
-XX:NewSize | 年轻代大小 | 表示新生代初始内存的大小,应该小于 -Xms的值; |
-XX:MaxNewSize | 年轻代最大值 | 表示新生代可被分配的内存的最大上限;当然这个值应该小于 -Xmx的值; |
-XX:NewRatio | 年轻代与年老代的比值 | 设置为4,则年轻代与年老代所占比值为1:4,年轻代占整个堆栈的1/5 |
-Xmn | 年轻代大小 | 这个参数则是对 -XX:newSize、-XX:MaxnewSize两个参数的同时配置,也就是说如果通过-Xmn来配置新生代的内存大小,那么-XX:newSize = -XX:MaxnewSize = -Xmn, Sun官方推荐配置为整个堆的3/8, |
-Xss | 每个线程的Stack大小 | JDK5.0以后每个线程堆栈大小为1M |
-XX:SurvivorRatio | 年轻代中Eden区与Survivor区的大小比值。 | 设置为4,则一个Eden区与两个Survivor区的比值为4:2,一个Survivor区占整个年轻代的1/6 |
-XX:PermSize | 持久代初始值 | 表示非堆区初始内存分配大小,其缩写为permanent size(持久化内存), 默认是物理内存的1/64 |
-XX:MaxPermSize | 持久代量大值 | 表示对非堆区分配的内存的最大上限。 默认是物理内存的1/4 |
空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制;
空余堆内存大于70%时,JVM会减少堆直到- Xms的最小限制。
因此服务器一般设置-Xms、-Xmx相等以避免在每次GC 后调整堆的大小。
在JDK8之前的HotSpot JVM,存放这些”永久的”的区域叫做“永久代(permanent generation)”。永久代是一片连续的堆空间,在JVM启动之前通过在命令行设置参数-XX:MaxPermSize来设定永久代最大可分配的内存空间,默认大小是64M(64位JVM由于指针膨胀,默认是85M)。永久代的垃圾收集是和老年代(old generation)捆绑在一起的,因此无论谁满了,都会触发永久代和老年代的垃圾收集。
而在JDK8里面移除了永生代,而对于存放类的元数据的内存大小的设置变为Metaspace参数,可以通过参数-XX:MetaspaceSize 和-XX:MaxMetaspaceSize设定大小。从JDK7开始符号引用(Symbols)转移到了native heap;字面量(interned strings)转移到了java heap;类的静态变量(class statics)转移到了java heap。在JDK7之前的版本,对于HopSpot JVM,interned-strings存储在永久代(又名PermGen),会导致大量的性能问题和OOM错误。
最大内存限制:
64位操作系统没有限制,32位系统有如下限制:
Windows:1.5G-2G,
Linux:2G-3G
异常:
当堆不够时(年轻代不够)会抛出异常:
java.lang.OutOfMemoryError: Java heap space
需要设置:-Xms1024m -Xmx1024m -XX:MaxNewSize=394m
当线程栈不够时抛:
Exception in thread "main" java.lang.StackOverflowError
需要设置:-Xss
当持久代不够时抛:
Exception in thread "main" java.lang.OutOfMemoryError: PermGen space
需要设置:-XX:PermSize=128M -XX:MaxPermSize=512m
调整jvm内存大小的方法
方法一:处理tomcat
Windows:
在tomcat的bin目录下,修改catalina.bat文件,在goHome后面添加:
set "JAVA_OPTS=%JAVA_OPTS% -Xms1024m -Xmx1024m -XX:MaxNewSize=394m"
但是如果不是执行startup.bat启动tomcat而是利用windows的系统服务启动tomcat服务,上面的设置就不生效了.windows服务执行的是bin\tomcat.exe.他读取注册表中的值,而不是catalina.bat的设置.
解决办法:
修改注册表HKEY_LOCAL_MACHINE\SOFTWARE\Apache Software Foundation\
Tomcat Service Manager\Tomcat5\Parameters\JavaOptions
原值为
-Dcatalina.home="C:\ApacheGroup\Tomcat 5.0"
-Djava.endorsed.dirs="C:\ApacheGroup\Tomcat 5.0\common\endorsed"-Xrs
加入 -Xms300m -Xmx350m
重起tomcat服务,设置生效
Linux:
在catalina.sh 的第一行加入以下内容:
JAVA_OPTS="$JAVA_OPTS -server -Xms1024m -Xmx1024m -XX:MaxNewSize=512m -Xss8m -XX:PermSize=1024M -XX:MaxPermSize=1024m"
方法二:eclipse
在eclipse的根目录有一个eclipse.ini文件,在最后有如下内容:
可直接修改。
方法三:启动时指定
在linux环境下运行jar包时,可直接加上参数,如:
java -Xms256m -Xmx1024m -jar xxx.jar