转自:http://blog.163.com/itjin45@126/blog/static/10510751320144201519454/html
官方手册:
http://docs.oracle.com/javase/7/docs/ ---->
http://docs.oracle.com/javase/7/docs/technotes/tools/solaris/java.html java命令的各类选项的说明java
参考书籍:mysql
《深刻理解Java虚拟机:JVM高级特性与最佳实践(第2版)》算法
首先说下JVM的内存堆结构,看下图:sql
主要由 方法区Permanent Generation + 新生代Eden + 新生代幸存区S0和S1 + 老年代Old Generation;
大部分新生成的对象都放在Eden中,当Eden内存不够用时,触发Young GC,这时,会将Eden中不能被释放的对象以及S0中幸存的对象,都Copy到S1中,而且将经历过几回Young GC还幸存的新生代对象,放入到Old Generation中,而后释放Eden和S0;json
因此S0和S1是来回切换使用的,保存新生代中还不能被释放的对象,因此S0和S1总有一个会是空的,固然在发生Youg GC时,对象正在COPY时会是两者都有数据;
若是经历几回Young GC时新生代仍是满的,还不可以接收Eden中过来的幸存对象,就会抛出java.lang.OutOfMemorryError:java heap space;api
若是在进行Youg GC时,发现S0不够用时,则直接将对象放入Old Generation中,这时若是Old Generation内存也不够时,则触发Full GC,Full GC后若是Old Generation仍是满的,就抛出内存溢出异常:
java.lang.OutOfMemorryError:java heap space;数组
因此,假设有一个永不销毁的对象,其经历的过程以下:首先在建立时放入Eden,当某个时刻Eden满了时,经过Young GC放入S0或者S1,其在S0或者S1经历过几回Youg GC后,放入到Old generation中,当Old Generation满了的时候,发生Full GC.缓存
这里有点须要注意,代码区(方法区),并不属于堆空间,他是一个单独的空间,其中保存有虚拟机本身的静态数据,以及加载的Class类级别静态对象,如class自己,method,field等,固然若是这部分空间不足时,同样会触发Full GC.并且若是GC以后仍是满的,就会抛出PermGen Space异常服务器
上面说到了堆和方法区,接下来咱们看下完整的JVM内存结构:
以前说了堆结构和代码区Permanent Space,顺着这个内存结构图,说下Code Generation,JVM本身内部使用的一块区域,用来编译和保存本地代码(native code),基本不会致使内存异常。若是该操做没有足够的空间,JVM可能会致使崩溃
Socket Buffers:用来作网络通讯的缓冲区,分为发送去和接收区,须要在java代码中控制它,因此外部没法配置。这里若是满了的话,会致使IOException: Too many open files 。
Thread JVM Stack:java的线程栈,java分配一个对象时,对象的具体内容在堆中,而对象的引用则位于栈中,也就是这里。并且方法的局部变量以及函数地址的调入和调出,都存放在这里,因此,JAVA的一个对象,有两部分,对象自己的值在堆中,而引用则在栈中。当栈空间不够时,好比递归层次太深,就会致使java.lang.StackOverflowError异常
Direct Memory Space:他可让开发人员映射内存到java Object Heap外
JNI Code :JNI code自己使用的内存很是小。
JNI allocate memory:JNI 程序自己也须要分配内存。
Garbage Collection:其实GC也是须要内存的,gc线程的消耗以及存放GC所缓存的信息。
因此,java进程实际占用并不等于堆内存的大小,很显然还有栈呀代码区呀什么之类的内存的大小。
再看一个列子,一个进程,设置的启动参数中,堆的最大内存指定为30G,而经过TOP命令,查看的内存使用状况为:
显然,这里的虚拟内存大小变成了38G,远远超过指定的堆的大小30G,究其缘由,一是,进程占用的内存除了堆,还有栈空间之类的,就是上面标红的一部分,二是,虚拟内存表示java像操做系统申请了38G,可是实际使用只有27G。在操做系统级别,内存是按页分配的,并且,若是你申请了空间,不访问它,那么虚拟内存使用大小是你申请的大小,而RES倒是0,当你访问时,若是物理内存不足,就有可能致使要访问的内存页不在物理内存里,会发生缺页中断,发生CPU的上下文切换,性能会降低,而这时RES才会增大。并且从经验来看Xms和Xmx是告诉JAVA,我实际要使用的堆的最大值是多少,也就是RES是多少,也就是说我实际有可能要放28G的对象进来,而咱们知道JVM的堆空间,S0和S1是切换的,因此,java实际须要向操做系统申请的空间确定大于28G,可是实际进程使用的却只有27G,这就是为何上图显示RES为27G而VIRT是38G。
jstat的整体使用参数说明
Option |
Displays… |
class loader的行为统计。Statistics on the behavior of the class loader. |
|
HotSpt JIT编译器行为统计。Statistics of the behavior of the HotSpot Just-in-Time compiler. |
|
垃圾回收堆的行为统计。Statistics of the behavior of the garbage collected heap. |
|
各个垃圾回收代容量(young,old,perm)和他们相应的空间统计。Statistics of the capacities of the generations and their corresponding spaces. |
|
垃圾收集统计概述(同-gcutil),附加最近两次垃圾回收事件的缘由。Summary of garbage collection statistics (same as -gcutil), with the cause of the last and |
|
新生代行为统计。Statistics of the behavior of the new generation. |
|
新生代与其相应的内存空间的统计。Statistics of the sizes of the new generations and its corresponding spaces. |
|
年老代和永生代行为统计。Statistics of the behavior of the old and permanent generations. |
|
年老代行为统计。Statistics of the sizes of the old generation. |
|
永生代行为统计。Statistics of the sizes of the permanent generation. |
|
垃圾回收统计概述。Summary of garbage collection statistics. |
|
HotSpot编译方法统计。HotSpot compilation method statistics. |
-h n
每隔n个样本 (行),n是正整数,
缺省为0,表明只有第一行为列头。
-t n
第一行输出为时间戳,
它表示自从目标JVM启动以来逝去的时间,以秒为单位。
如何查看JVM的性能呢?如今给出实际的列子:
一、查看java命令启动参数
jinfo 20611
Attaching to process ID 20611, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 19.1-b02
Java System Properties:
java.runtime.name = Java(TM) SE Runtime Environment
sun.boot.library.path = /usr/lib/jvm/java-1.6.0-sun-1.6.0.24.x86_64/jre/lib/amd64
java.vm.version = 19.1-b02
java.vm.vendor = Sun Microsystems Inc.
java.vendor.url = http://java.sun.com/
path.separator = :
java.vm.name = Java HotSpot(TM) 64-Bit Server VM
file.encoding.pkg = sun.io
sun.java.launcher = SUN_STANDARD
user.country = US
sun.os.patch.level = unknown
java.vm.specification.name = Java Virtual Machine Specification
user.dir = /mezi/dps/local/investopedia-market-service
java.runtime.version = 1.6.0_24-b07
java.awt.graphicsenv = sun.awt.X11GraphicsEnvironment
java.endorsed.dirs = /usr/lib/jvm/java-1.6.0-sun-1.6.0.24.x86_64/jre/lib/endorsed
os.arch = amd64
java.io.tmpdir = /tmp
line.separator =
java.vm.specification.vendor = Sun Microsystems Inc.
os.name = Linux
sun.jnu.encoding = UTF-8
java.library.path = /usr/lib/jvm/java-1.6.0-sun-1.6.0.24.x86_64/jre/lib/amd64/server:/usr/lib/jvm/java-1.6.0-sun-1.6.0.24.x86_64/jre/lib/amd64:/usr/lib/jvm/java-1.6.0-sun-1.6.0.24.x86_64/jre/../lib/amd64:/usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib
java.specification.name = Java Platform API Specification
java.class.version = 50.0
sun.management.compiler = HotSpot 64-Bit Server Compiler
os.version = 2.6.18-348.12.1.el5
user.home = /home/mmdps
user.timezone = UTC
java.awt.printerjob = sun.print.PSPrinterJob
file.encoding = UTF-8
java.specification.version = 1.6
java.class.path = :libs/aopalliance.jar:libs/axiom-api-1.2.13.jar:libs/axiom-impl-1.2.13.jar:libs/axis2-adb-1.6.2.jar:libs/axis2-kernel-1.6.2.jar:libs/axis2-transport-http-1.6.2.jar:libs/axis2-transport-local-1.6.2.jar:libs/axis2-xmlbeans-1.6.2.jar:libs/bonecp-0.7.1.RELEASE.jar:libs/commons-codec-1.3.jar:libs/commons-httpclient-3.1.jar:libs/commons-lang-2.5.jar:libs/ehcache-2.7.1.jar:libs/google-collections-1.0.jar:libs/gson-2.2.4.jar:libs/guice-3.0.jar:libs/httpcore-4.0.jar:libs/javax.inject.jar:libs/jetty-client-8.1.10.v20130312.jar:libs/jetty-continuation-8.1.10.v20130312.jar:libs/jetty-http-8.1.10.v20130312.jar:libs/jetty-io-8.1.10.v20130312.jar:libs/jetty-security-8.1.10.v20130312.jar:libs/jetty-server-8.1.10.v20130312.jar:libs/jetty-servlet-8.1.10.v20130312.jar:libs/jetty-util-8.1.10.v20130312.jar:libs/jetty-xml-8.1.10.v20130312.jar:libs/json-rpc-1.0.jar:libs/log4j-1.2.15.jar:libs/mail-1.4.jar:libs/mockito-all-1.9.0.jar:libs/mysql-connector-java-5.1.7-bin.jar:libs/neethi-3.0.2.jar:libs/quartz.jar:libs/servlet-api-3.0.jar:libs/slf4j-api-1.7.5.jar:libs/slf4j-log4j12-1.7.5.jar:libs/start.jar:libs/wsdl4j-1.6.2.jar:libs/xmlbeans-2.3.0.jar:libs/XmlSchema-1.4.7.jar:properties:resources
user.name = mmdps
java.vm.specification.version = 1.0
java.home = /usr/lib/jvm/java-1.6.0-sun-1.6.0.24.x86_64/jre
sun.arch.data.model = 64
user.language = en
java.specification.vendor = Sun Microsystems Inc.
java.vm.info = mixed mode
java.version = 1.6.0_24
java.ext.dirs = /usr/lib/jvm/java-1.6.0-sun-1.6.0.24.x86_64/jre/lib/ext:/usr/java/packages/lib/ext
sun.boot.class.path = /usr/lib/jvm/java-1.6.0-sun-1.6.0.24.x86_64/jre/lib/resources.jar:/usr/lib/jvm/java-1.6.0-sun-1.6.0.24.x86_64/jre/lib/rt.jar:/usr/lib/jvm/java-1.6.0-sun-1.6.0.24.x86_64/jre/lib/sunrsasign.jar:/usr/lib/jvm/java-1.6.0-sun-1.6.0.24.x86_64/jre/lib/jsse.jar:/usr/lib/jvm/java-1.6.0-sun-1.6.0.24.x86_64/jre/lib/jce.jar:/usr/lib/jvm/java-1.6.0-sun-1.6.0.24.x86_64/jre/lib/charsets.jar:/usr/lib/jvm/java-1.6.0-sun-1.6.0.24.x86_64/jre/lib/modules/jdk.boot.jar:/usr/lib/jvm/java-1.6.0-sun-1.6.0.24.x86_64/jre/classes
java.vendor = Sun Microsystems Inc.
file.separator = /
java.vendor.url.bug = http://java.sun.com/cgi-bin/bugreport.cgi
sun.io.unicode.encoding = UnicodeLittle
sun.cpu.endian = little
sun.cpu.isalist =
VM Flags:
-Xms2000m -Xmx8000m
二、 jstat -gc pid 查看垃圾回收统计
jstat -gc 50206 500 10
列名 |
描述 |
S0C |
当前survivor space 0容量。Current survivor space 0 capacity (KB). |
S1C |
survivor space 1容量。Current survivor space 1 capacity (KB). |
S0U |
Survivor space 0 利用状况。Survivor space 0 utilization (KB). |
S1U |
Survivor space 1 利用状况。Survivor space 1 utilization (KB). |
EC |
当前新生代eden空间容量。Current eden space capacity (KB). |
EU |
新生代eden空间利用状况。Eden space utilization (KB). |
OC |
当前年老代空间容量。Current old space capacity (KB). |
OU |
年老代利用状况。Old space utilization (KB). |
PC |
当前永生代空间容量。Current permanent space capacity (KB). |
PU |
永生代空间利用状况。Permanent space utilization (KB). |
YGC |
新生代GC事件次数。 Number of young generation GC Events. |
YGCT |
新生代GC耗时。Young generation garbage collection time. |
FGC |
full GC次数。Number of full GC events. |
FGCT |
full gc耗时。Full garbage collection time. |
GCT |
总GC耗时。Total garbage collection time. |
三、GC内存空间使用统计
jstat -gccapacity 20611 500 5
列名 |
描述 |
NGCMN |
最小新生代容量。Minimum new generation capacity (KB). |
NGCMX |
最大新生代容量。Maximum new generation capacity (KB). |
NGC |
当前新生代容量。Current new generation capacity (KB). |
S0C |
当前新生代survivor 0区容量。Current survivor space 0 capacity (KB). |
S1C |
当前新生代survivor 1区容量。Current survivor space 1 capacity (KB). |
EC |
当前新生代eden空间容量。Current eden space capacity (KB). |
OGCMN |
最小年老代容量。Minimum old generation capacity (KB). |
OGCMX |
最大年老代容量。Maximum old generation capacity (KB). |
OGC |
当前年老代容量。Current old generation capacity (KB). |
OC |
当前年老代空间容量。Current old space capacity (KB). |
PGCMN |
最小永生代容量。Minimum permanent generation capacity (KB). |
PGCMX |
最大永生代容量。Maximum Permanent generation capacity (KB). |
PGC |
当前新生成的永生代容量。Current Permanent generation capacity (KB). |
PC |
当前永生代空间容量。Current Permanent space capacity (KB). |
YGC |
新生代GC次数。Number of Young generation GC Events. |
FGC |
Full GC次数。Number of Full GC Events. |
四、GC内存空间各区使用比例
jstat -gcutil 20611 500 5
列名 |
描述 |
S0 |
survivor 0区利用率。 |
S1 |
survivor 1区利用率。 |
E |
eden区利用率。 |
O |
年老代空间利用率。 |
P |
永生代空间利用率。Permanent space utilization as a percentage of |
YGC |
young gc次数。 |
YGCT |
young gc耗时。 |
FGC |
full gc次数。 |
FGCT |
full gc耗时。 |
GCT |
GC总耗时。 |
列名 |
描述 |
LGCC |
上次GC缘由。Cause of last Garbage Collection. |
GCC |
本次GC缘由。Cause of current Garbage Collection. |
列名 |
描述 |
S0C |
当前survivor 0区容量。Current |
S1C |
当前survivor 1区容量。Current |
S0U |
当前survivor 0区利用状况。 |
S1U |
当前survivor 1区利用状况。 |
TT |
阀值, 用于控制对象在新生代存活的次数。 |
MTT |
阀值, 用于控制对象在新生代存活的最大次数。Maximum tenuring threshold. |
DSS |
指望存活大小。 |
EC |
当前eden空间容量。Current eden space capacity (KB). |
EU |
eden空间利用状况。 |
YGC |
年轻代gc次数。Number of young generation GC events. |
YGCT |
年轻代GC耗时。 |
note: 若某个age上的survivor space对象的大小若是超过Desired survivor size,则从新计算tenuring threshold,以age和MaxTenuringThreshold的最小值为准
七、新生代空间统计
jstat -gcnewcapacity 20611 500 5
列名 |
描述 |
NGCMN |
最小新生代容量。Minimum new generation capacity (KB). |
NGCMX |
最大新生代容量。Maximum new generation capacity (KB). |
NGC |
当前新生代容量。Current new generation capacity (KB). |
S0CMX |
最大survivor 0区容量。Maximum survivor space 0 capacity (KB). |
S0C |
当前survivor 0区容量。Current survivor space 0 capacity (KB). |
S1CMX |
最大survivor 1区容量。Maximum |
S1C |
当前survivor 1区容量。Current survivor space 1 capacity (KB). |
ECMX |
最大eden区容量。Maximum eden space capacity (KB). |
EC |
当前eden区容量。Current eden space capacity (KB). |
YGC |
young gc次数。 |
FGC |
full gc次数。Number of Full GC Events. |
八、年老代使用状况
jstat -gcold 20611 500 5
列名 |
描述 |
PC |
当前永久代空间容量。Current permanent space capacity (KB). |
PU |
永久代空间利用状况。Permanent space utilization (KB). |
OC |
当前年老代空间容量。Current old space capacity (KB). |
OU |
年老代空间利用状况。 |
YGC |
young gc次数。 |
FGC |
full gc次数。Number of full GC events. |
FGCT |
full gc耗时。 |
GCT |
gc总耗时。 |
九、年老代空间容量
jstat -gcoldcapacity 20611 500 5
列名 |
描述 |
OGCMN |
最小年老代容量。Minimum |
OGCMX |
最大年老代容量。Maximum |
OGC |
当前年老代容量。Current |
OC |
当前年老代空间容量。Current |
YGC |
young gc次数。 |
FGC |
full gc次数。 |
FGCT |
full gc耗时。Full garbage collection time. |
GCT |
总GC耗时。 |
十、永生代统计
jstat -gcpermcapacity 20611 500 5
列名 |
描述 |
PGCMN |
Minimum permanent generation capacity (KB). |
PGCMX |
Maximum permanent generation capacity (KB). |
PGC |
Current permanent generation capacity (KB). |
PC |
Current permanent space capacity (KB). |
YGC |
Number of young generation GC events. |
FGC |
Number of full GC events. |
FGCT |
Full garbage collection time. |
GCT |
Total garbage collection time. |
十一、编译统计
jstat -printcompilation 20611 500 5
列名 |
描述 |
Compiled |
执行的编译任务次数 |
Size |
Number of bytes of bytecode for the method. |
Type |
编译类型。Compilation type. |
Method |
类名和方法名。类名使用”/”代替了原命名空间符号”.” |
jstat -class 20611 500 5
列名 |
描述 |
Loaded |
已加载的类个数。 |
Bytes |
已加载类占用字节数(KB为单位)。 |
Unloaded |
卸载的类个数。 |
Bytes |
卸载的类占用字节数(KB为单位)。 |
Time |
加载和卸载操做花费的时间。 |
jinfo flag ThreadStackSize 20611 :-XX:ThreadStackSize=1024
先看持久代,参数设置为:XX:PermSize 最小值,XX:MaxpermSize最大值
使用 jinfo -flag PermSize 20611 + jinfo -flag MaxPermSize 20611 看到值分别为:
-XX:PermSize=21757952 -XX:MaxPermSize=85983232,由于上面的进程,咱们没配置它,因此这两个值就是默认值,一个是20.75M,一个是82M,
这个与 jstat -gcpermcapacity 20611 500 5命令中的 PGCMN = 21248.0 KB 和 PGCMX= 83968.0 KB是相吻合的,同时咱们看到当前容量为31M,
因此,这个总容量是没太大问题的,可是这里会发生在GC以后内存收缩状况,因此咱们通常都设置成 XX:PermSize=XX:MaxPermSize
实验1(持久代),咱们用参数配置后再来启动它, -XX:PermSize=50M -XX:MaxPermSize=100M,使用 jstat -gcpermcapacity命令后发现PGCMN=51200
PGCMX=102400,PGC=51200,因此,和咱们指望的是同样的,可是若是想看咱们实际占用了多少呢?经过jstat -gc 19539 命令,能够发现
PC=51200,PU=29174.4,说明咱们实际是用了29M。
反过来,由于咱们知道咱们的进程须要占用29M的空间,当咱们把 -XX:PermSize=10M -XX:MaxPermSize=10M配置成最多使用10M时,启动进程就会发现报了以下错误:
Exception in thread "main" java.lang.OutOfMemoryError: PermGen space
看下新生代区,一共有这几个参数能够影响到其大小: 指定年轻代的大小(Eden+S0+S1);-XX:NewSize设置年轻代初始化值大小;-XX:MaxNewSize设置年轻代最大值,
-XX:NewRatio年轻代与年老代的比值,Xms=Xmx而且设置了Xmn的状况下,该参数不须要进行设置;-XX:SurvivorRatio设置Survivor与Eden之间的比值,若是设置为8,则表示
一个Surivior(S0)为1,Eden为8,因此,S0占年轻代的1/10,S1占1/10,Eden占8/10
先使用jinfo -falg看下这些值的默认配置:-XX:NewSize=1310720 -XX:MaxNewSize=18446744073709486080(无限制) -XX:NewRatio=2 -XX:SurvivorRatio=8
当我使用java -server -Xmn3000M -XX:SurvivorRatio=8 -XX:NewSize=3000M -XX:MaxNewSize=3000M -XX:PermSize=500M -XX:MaxPermSize=500M -Xms2000m -Xmx8000m该参数时启动会报错,Error occurred during initialization of VM ,Too small initial heap for new size specified,缘由在于-Xms指定初始化堆大小为2000M,而最小新生代-Xmn3000都比该值大,这个是不容许的,因此,
调整后的参数为:java -server -Xmn3000M -XX:SurvivorRatio=8 -XX:NewSize=3000M -XX:MaxNewSize=3000M -XX:PermSize=500M -XX:MaxPermSize=500M -Xms8000m -Xmx8000m
使用jstat -gcnewcapacity 26111命令发现,最小最大新生代的大小确实都是3000M,但奇怪的是S0\S1\Eden的最大值也都是3000M,Eden实际容量是2400M,
这说明这种状况下-XX:SurvivorRatio=8这个参数不起做用了。
而通常咱们配置XX:SurvivorRatio=1从而使新生代Eden=S0=S1,而且Xmn设置新生代的大小
调整后的参数为:-Xmn3000M -XX:SurvivorRatio=1 -XX:PermSize=500M -XX:MaxPermSize=500M -Xms8000m -Xmx8000m
这时候再使用gcnewcapacity就会发现:NGCMN=NGCMX=NGC=3000M,lS0C=S1C=EC=1024000,跟咱们预期的彻底同样!
可是运行一段时间之后,发现值稍微有了一些变化,S0C=1024000,S1C=836224,EC=1360512,就是EC变大了,而S1变小了,至于为何,不得而已???
其余的一些设置:
-XX:+UseConcMarkSweepGC 使用CMS模式进行垃圾回收,该机制的特色是并发收集、低停顿,但同时,也会产生一些碎片和浮动垃圾,由于CMS并发清理阶段用户线程还在运行着,伴随程序的运行天然还会有新的垃这一部分垃圾出如今标记过程以后,CMS没法在本次收集中处理掉它们,只好留待下一次GC时再将其清理掉,这部分就是浮动垃圾。
-XX:+UseCMSCompactAtFullCollection,在FULL GC的时候, 对年老代的压缩。因为启动了CMS机制进行垃圾收集,其会产生碎片,因此圾不断产生,因此该选择须要配合上面这个选择,CMS收集器一块儿使用
-XX:CMSInitiatingOccupancyFraction=70 使用cms做为垃圾回收,使用70%后开始CMS收集。为了保证不出现promotion failed(见下面介绍)错误,该值的设置须要知足如下公式CMSInitiatingOccupancyFraction计算公式
CMSInitiatingOccupancyFraction值与Xmn的关系公式
上面介绍了promontion faild产生的缘由是EDEN空间不足的状况下将EDEN与From survivor中的存活对象存入To survivor区时,To survivor区的空间不足,再次晋升到old gen区,而old gen区内存也不够的状况下产生了promontion faild从而致使full gc.那能够推断出:eden+from survivor < old gen区剩余内存时,不会出现promontion faild的状况,即:
(Xmx-Xmn)*(1-CMSInitiatingOccupancyFraction/100)>=(Xmn-Xmn/(SurvivorRatior+2)) 进而推断出:
CMSInitiatingOccupancyFraction <=((Xmx-Xmn)-(Xmn-Xmn/(SurvivorRatior+2)))/(Xmx-Xmn)*100
-XX:+UseParNewGC |
设置年轻代为并行收集 |
|
可与CMS收集同时使用 |
-XX:ParallelGCThreads |
并行收集器的线程数 |
|
此值最好配置与处理器数目相等 一样适用于CMS |
网上一个很NB的配置参考:
$JAVA_ARGS
.=
"
-Dresin.home=$SERVER_ROOT
-server
-Xmx3000M
-Xms3000M
-Xmn600M
-XX:PermSize=500M
-XX:MaxPermSize=500M
-Xss256K
-XX:+DisableExplicitGC
-XX:SurvivorRatio=1
-XX:+UseConcMarkSweepGC
-XX:+UseParNewGC
-XX:+CMSParallelRemarkEnabled
-XX:+UseCMSCompactAtFullCollection
-XX:CMSFullGCsBeforeCompaction=0
-XX:+CMSClassUnloadingEnabled
-XX:LargePageSizeInBytes=128M
-XX:+UseFastAccessorMethods
-XX:+UseCMSInitiatingOccupancyOnly
-XX:CMSInitiatingOccupancyFraction=70
-XX:SoftRefLRUPolicyMSPerMB=0
-XX:+PrintClassHistogram
-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps
-XX:+PrintHeapAtGC
-Xloggc:log/gc.log
";
64位jdk参考设置,年老代涨得很慢,CMS执行频率变小,CMS没有停滞,也不会有promotion failed问题,内存回收得很干净
颇有用的一个各参数说明:
JVM参数的含义 实例见实例分析
参数名称 |
含义 |
默认值 |
|
-Xms |
初始堆大小 |
物理内存的1/64(<1GB) |
默认(MinHeapFreeRatio参数能够调整)空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制. |
-Xmx |
最大堆大小 |
物理内存的1/4(<1GB) |
默认(MaxHeapFreeRatio参数能够调整)空余堆内存大于70%时,JVM会减小堆直到 -Xms的最小限制 |
-Xmn |
年轻代大小(1.4or lator) |
|
注意:此处的大小是(eden+ 2 survivor space).与jmap -heap中显示的New gen是不一样的。 |
-XX:NewSize |
设置年轻代大小(for 1.3/1.4) |
|
|
-XX:MaxNewSize |
年轻代最大值(for 1.3/1.4) |
|
|
-XX:PermSize |
设置持久代(perm gen)初始值 |
物理内存的1/64 |
|
-XX:MaxPermSize |
设置持久代最大值 |
物理内存的1/4 |
|
-Xss |
每一个线程的堆栈大小 |
|
JDK5.0之后每一个线程堆栈大小为1M,之前每一个线程堆栈大小为256K.更具应用的线程所需内存大小进行 调整.在相同物理内存下,减少这个值能生成更多的线程.可是操做系统对一个进程内的线程数仍是有限制的,不能无限生成,经验值在3000~5000左右 |
-XX:ThreadStackSize |
Thread Stack Size |
|
(0 means use default stack size) [Sparc: 512; Solaris x86: 320 (was 256 prior in 5.0 and earlier); Sparc 64 bit: 1024; Linux amd64: 1024 (was 0 in 5.0 and earlier); all others 0.] |
-XX:NewRatio |
年轻代(包括Eden和两个Survivor区)与年老代的比值(除去持久代) |
|
-XX:NewRatio=4表示年轻代与年老代所占比值为1:4,年轻代占整个堆栈的1/5 |
-XX:SurvivorRatio |
Eden区与Survivor区的大小比值 |
|
设置为8,则两个Survivor区与一个Eden区的比值为2:8,一个Survivor区占整个年轻代的1/10 |
-XX:LargePageSizeInBytes |
内存页的大小不可设置过大, 会影响Perm的大小 |
|
=128m |
-XX:+UseFastAccessorMethods |
原始类型的快速优化 |
|
|
-XX:+DisableExplicitGC |
关闭System.gc() |
|
这个参数须要严格的测试 |
-XX:MaxTenuringThreshold |
垃圾最大年龄 |
|
若是设置为0的话,则年轻代对象不通过Survivor区,直接进入年老代. 对于年老代比较多的应用,能够提升效率.若是将此值设置为一个较大值,则年轻代对象会在Survivor区进行屡次复制,这样能够增长对象再年轻代的存活 时间,增长在年轻代即被回收的几率 |
-XX:+AggressiveOpts |
加快编译 |
|
|
-XX:+UseBiasedLocking |
锁机制的性能改善 |
|
|
-Xnoclassgc |
禁用垃圾回收 |
|
|
-XX:SoftRefLRUPolicyMSPerMB |
每兆堆空闲空间中SoftReference的存活时间 |
1s |
softly reachable objects will remain alive for some amount of time after the last time they were referenced. The default value is one second of lifetime per free megabyte in the heap |
-XX:PretenureSizeThreshold |
对象超过多大是直接在旧生代分配 |
0 |
单位字节 新生代采用Parallel Scavenge GC时无效 |
-XX:TLABWasteTargetPercent |
TLAB占eden区的百分比 |
1% |
|
-XX:+CollectGen0First |
FullGC时是否先YGC |
false |
|
并行收集器相关参数
-XX:+UseParallelGC |
Full GC采用parallel MSC |
|
选择垃圾收集器为并行收集器.此配置仅对年轻代有效.即上述配置下,年轻代使用并发收集,而年老代仍旧使用串行收集.(此项待验证) |
-XX:+UseParNewGC |
设置年轻代为并行收集 |
|
可与CMS收集同时使用 |
-XX:ParallelGCThreads |
并行收集器的线程数 |
|
此值最好配置与处理器数目相等 一样适用于CMS |
-XX:+UseParallelOldGC |
年老代垃圾收集方式为并行收集(Parallel Compacting) |
|
这个是JAVA 6出现的参数选项 |
-XX:MaxGCPauseMillis |
每次年轻代垃圾回收的最长时间(最大暂停时间) |
|
若是没法知足此时间,JVM会自动调全年轻代大小,以知足此值. |
-XX:+UseAdaptiveSizePolicy |
自动选择年轻代区大小和相应的Survivor区比例 |
|
设置此选项后,并行收集器会自动选择年轻代区大小和相应的Survivor区比例,以达到目标系统规定的最低相应时间或者收集频率等,此值建议使用并行收集器时,一直打开. |
-XX:GCTimeRatio |
设置垃圾回收时间占程序运行时间的百分比 |
|
公式为1/(1+n) |
-XX:+ScavengeBeforeFullGC |
Full GC前调用YGC |
true |
Do young generation GC prior to a full GC. (Introduced in 1.4.1.) |
CMS相关参数
-XX:+UseConcMarkSweepGC |
使用CMS内存收集 |
|
测试中配置这个之后,-XX:NewRatio=4的配置失效了,缘由不明.因此,此时年轻代大小最好用-Xmn设置.??? |
-XX:+AggressiveHeap |
|
|
试图是使用大量的物理内存 |
-XX:CMSFullGCsBeforeCompaction |
多少次后进行内存压缩 |
|
因为并发收集器不对内存空间进行压缩,整理,因此运行一段时间之后会产生"碎片",使得运行效率下降.此值设置运行多少次GC之后对内存空间进行压缩,整理. |
-XX:+CMSParallelRemarkEnabled |
下降标记停顿 |
|
|
-XX+UseCMSCompactAtFullCollection |
在FULL GC的时候, 对年老代的压缩 |
|
CMS是不会移动内存的, 所以, 这个很是容易产生碎片, 致使内存不够用, 所以, 内存的压缩这个时候就会被启用。 增长这个参数是个好习惯。 |
-XX:+UseCMSInitiatingOccupancyOnly |
使用手动定义初始化定义开始CMS收集 |
|
禁止hostspot自行触发CMS GC |
-XX:CMSInitiatingOccupancyFraction=70 |
使用cms做为垃圾回收 |
92 |
为了保证不出现promotion failed(见下面介绍)错误,该值的设置须要知足如下公式CMSInitiatingOccupancyFraction计算公式 |
-XX:CMSInitiatingPermOccupancyFraction |
设置Perm Gen使用到达多少比率时触发 |
92 |
|
-XX:+CMSIncrementalMode |
设置为增量模式 |
|
用于单CPU状况 |
-XX:+CMSClassUnloadingEnabled |
|
|
|
辅助信息
-XX:+PrintGC |
|
|
输出形式: [GC 118250K->113543K(130112K), 0.0094143 secs] |
-XX:+PrintGCDetails |
|
|
输出形式:[GC [DefNew: 8614K->781K(9088K), 0.0123035 secs] 118250K->113543K(130112K), 0.0124633 secs] |
-XX:+PrintGCTimeStamps |
|
|
|
-XX:+PrintGC:PrintGCTimeStamps |
|
|
可与-XX:+PrintGC -XX:+PrintGCDetails混合使用 |
-XX:+PrintGCApplicationStoppedTime |
打印垃圾回收期间程序暂停的时间.可与上面混合使用 |
|
输出形式:Total time for which application threads were stopped: 0.0468229 seconds |
-XX:+PrintGCApplicationConcurrentTime |
打印每次垃圾回收前,程序未中断的执行时间.可与上面混合使用 |
|
输出形式:Application time: 0.5291524 seconds |
-XX:+PrintHeapAtGC |
打印GC先后的详细堆栈信息 |
|
|
-Xloggc:filename |
把相关日志信息记录到文件以便分析. |
|
|
-XX:+PrintClassHistogram |
garbage collects before printing the histogram. |
|
|
-XX:+PrintTLAB |
查看TLAB空间的使用状况 |
|
|
XX:+PrintTenuringDistribution |
查看每次minor GC后新的存活周期的阈值 |
|
Desired survivor size 1048576 bytes, new threshold 7 (max 15) |
GC性能方面的考虑
对于GC的性能主要有2个方面的指标:吞吐量throughput(工做时间不算gc的时间占总的时间比)和暂停pause(gc发生时app对外显示的没法响应)。
1. Total Heap
默认状况下,vm会增长/减小heap大小以维持free space在整个vm中占的比例,这个比例由MinHeapFreeRatio和MaxHeapFreeRatio指定。
通常而言,server端的app会有如下规则:
2. The Young Generation
另一个对于app流畅性运行影响的因素是young generation的大小。young generation越大,minor collection越少;可是在固定heap size状况下,更大的young generation就意味着小的tenured generation,就意味着更多的major collection(major collection会引起minor collection)。
NewRatio反映的是young和tenured generation的大小比例。NewSize和MaxNewSize反映的是young generation大小的下限和上限,将这两个值设为同样就固定了young generation的大小(同Xms和Xmx设为同样)。
若是但愿,SurvivorRatio也能够优化survivor的大小,不过这对于性能的影响不是很大。SurvivorRatio是eden和survior大小比例。
通常而言,server端的app会有如下规则:
经验&&规则
响应时间优先的应用:年老代使用并发收集器,因此其大小须要当心设置,通常要考虑并发会话率和会话持续时间等一些参数.若是堆设置小了,能够会形成内存碎 片,高回收频率以及应用暂停而使用传统的标记清除方式;若是堆大了,则须要较长的收集时间.最优化的方案,通常须要参考如下数据得到:
并发垃圾收集信息、持久代并发收集次数、传统GC信息、花在年轻代和年老代回收上的时间比例。
promotion failed:
垃圾回收时promotion failed是个很头痛的问题,通常多是两种缘由产生,第一个缘由是救助空间不够,救助空间里的对象还不该该被移动到年老代,但年轻代又有不少对象须要放入救助空间;第二个缘由是年老代没有足够的空间接纳来自年轻代的对象;这两种状况都会转向Full GC,网站停顿时间较长。
解决方方案一:
第一个缘由个人最终解决办法是去掉救助空间,设置-XX:SurvivorRatio=65536 -XX:MaxTenuringThreshold=0便可,第二个缘由个人解决办法是设置CMSInitiatingOccupancyFraction为某个值(假设70),这样年老代空间到70%时就开始执行CMS,年老代有足够的空间接纳来自年轻代的对象。
解决方案一的改进方案:
又有改进了,上面方法不太好,由于没有用到救助空间,因此年老代容易满,CMS执行会比较频繁。我改善了一下,仍是用救助空间,可是把救助空间加大,这样也不会有promotion failed。具体操做上,32位Linux和64位Linux好像不同,64位系统彷佛只要配置MaxTenuringThreshold参数,CMS仍是有暂停。为了解决暂停问题和promotion failed问题,最后我设置-XX:SurvivorRatio=1 ,并把MaxTenuringThreshold去掉,这样即没有暂停又不会有promotoin failed,并且更重要的是,年老代和永久代上升很是慢(由于好多对象到不了年老代就被回收了),因此CMS执行频率很是低,好几个小时才执行一次,这样,服务器都不用重启了。
-Xmx4000M -Xms4000M -Xmn600M -XX:PermSize=500M -XX:MaxPermSize=500M -Xss256K -XX:+DisableExplicitGC -XX:SurvivorRatio=1 -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction=0 -XX:+CMSClassUnloadingEnabled -XX:LargePageSizeInBytes=128M -XX:+UseFastAccessorMethods -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=80 -XX:SoftRefLRUPolicyMSPerMB=0 -XX:+PrintClassHistogram -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintHeapAtGC -Xloggc:log/gc.log
CMSInitiatingOccupancyFraction值与Xmn的关系公式
上面介绍了promontion faild产生的缘由是EDEN空间不足的状况下将EDEN与From survivor中的存活对象存入To survivor区时,To survivor区的空间不足,再次晋升到old gen区,而old gen区内存也不够的状况下产生了promontion faild从而致使full gc.那能够推断出:eden+from survivor < old gen区剩余内存时,不会出现promontion faild的状况,即:
(Xmx-Xmn)*(1-CMSInitiatingOccupancyFraction/100)>=(Xmn-Xmn/(SurvivorRatior+2)) 进而推断出:
参考图:
四,JVM 内存参数分析实例
环境:OS:Linux version 2.6.9-79.custome.ELxenU cpu: 4 * Intel(R) Xeon(R) CPU E5410 @ 2.33GHz (双核) memory:4G
1 |
de style="line-height: 16px; font-family: Consolas, 'Bitstream Vera Sans Mono', 'Courier New', Courier, monospace !important; font-size: 1em !important;" >-server -Xmx2g -Xms2g -Xmn256m -XX:PermSize=192m -Xss256k -XX:+DisableExplicitGC -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:LargePageSizeInBytes=128m -XX:+UseFastAccessorMethods -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70de> |
-Xmx2g 最大堆内存2G
-Xms2g 最小内存2G
-Xmn256m 新生代内存256m 整个堆大小=年轻代大小 + 年老代大小 + 持久代大小。持久代通常是固定大小的(例如64m、96m),因此增大年轻代后,将会减少年老代大小。此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8。
-XX:PermSize=192m 持久代 192m
-Xss256k 指定线程桟大小256K
-XX:LargePageSizeInBytes=128m 指定Java heap的分页页面大小为128M
-server 可使得新生代采用并行GC,年老代采用串行
-XX:+DisableExplicitGC
-XX:+UseConcMarkSweepGC 指定在Old Generation使用concurrent gc ,启用CMS低停顿垃圾收集器。GC线程和应用线程并行
-XX:+CMSParallelRemarkEnabled
-XX:+UseCMSCompactAtFullCollection
-XX:+UseFastAccessorMethods
-XX:+UseCMSInitiatingOccupancyOnly
-XX:CMSInitiatingOccupancyFraction=70
五. 内存回收
GC:垃圾回收。回收的是堆和方法区的内存。
基本原理:找到不被使用的对象,而后回收内存。使用收集器的方式实现GC。
A)怎么找到?从根集合出发,找出无引用的对象。
根集合对象: 当前运行线程栈上引用的对象,常量及静态变量,传到本地方法且没有被本地方法释放的对象引用。
B)收集器
按回收算法为两种: 引用计数收集器,跟踪收集器。
引用计数采用算法:原理是此对象有一个引用,即增长一个计数,删除一个引用则减小一个计数。垃圾回收时,只用收集计数为0的对象。
跟踪收集器采用算法:复制,标记-清除,标记-压缩。
按分区对待的方式分: 增量收集器(jdk5开始废弃),分代收集器。
增量收集器:就是经过必定的回收算法,把一个长时间的中断,划分为不少个小的中断,经过这种方式减小GC对用户程序的影响。
分代收集:对象存活的时间有长短,基于此将堆分为多个代,不一样的代采用不一样的GC方式。
按吞吐量和响应时间(暂停时间)分为: 串行收集器,并行收集器,并发收集器。
C)评估垃圾回收策略的两个重要度量
吞吐量:JVM花费在垃圾回收上的时间越长,则吞吐量越低
暂停时间:JVM垃圾回收过程中有一个暂停期,在暂停期间,应用程序不能运行
串行收集器:单线程(单CPU)进行垃圾回收的工做。
–适用状况:数据量比较小;单处理器下而且对响应时间无要求的应用。
–缺点:只能用于小型应用
并行收集器:多个线程同时进行垃圾回收的工做。
–适用状况:”对吞吐量有高要求”,多CPU、对应用响应时间无要求的中、大型应用。举例:科学计算。
–缺点:应用响应时间可能较长
并发收集器:传说中的CMS。垃圾回收器的一些工做与应用程序同时进行。
–适用状况:”对响应时间有高要求”,多CPU、对应用响应时间有较高要求的中、大型应用。举例:Web服务器/应用服务器。
D)GC类型
GC有两种类型:Minor GC(Scavenge GC)和Full GC。
Minor GC:对新生代内存进行GC。
Full GC:对新生代,旧生代,持久代都进行GC。
Full GC可能的缘由:
a)老年代或持久代空间满。
b)老年代采用CMS GC,GC日志出现prmotion failed和concurrent mode failure时可能触发。
prmotion failed:Minor GC是,S0(S1)放不下,放入旧生代时,仍然放不下形成的。
concurrent mode failure:CMS GC的过程当中,有对象放入旧生代,此时旧生代空间不够。
c)统计获得Minor GC后存活对象放入旧生代的平均大小大于旧生代剩余空间。
d)System.gc(),只是”建议”JVM回收内存,不是强制。
六. 为什么内存溢出:
既然都有GC,为何还有内存被用尽(固然除了忽然申请大空间)。这里更想说的是新生代和老年代被耗尽。
这是由于jvm有四种引用类型,不一样的引用,GC的条件是不同的。
A)四种引用
软引用:SoftReference,弱引用:WeakReference ,虚引用:PhantomReference。
软引用:内存不足,或软引用不常用时会被回收。适用于作缓存。
弱引用:使用弱引用建立的对象自己没有强引用,GC时必定会被回收。
虚引用:虚引用并不会决定对象的生命周期。若是一个对象仅持有虚引用,那么它就和没有任何引用同样,在任什么时候候均可能被垃圾回收。
除此以外都是强引用,咱们通常建立一个对象时的引用就是强引用。对象被强引用,是不会不垃圾回收的。
B)内存溢出(泄露)
两种理解,
一是须要使用的对象在不断增长,直到须要分配的jvm内存超出了没法知足,因而产生溢出。
二是无用的对象在不断增长,但又没法回收,因而产生泄露。
泄露的对象有两个特色,首先,这些对象是可达的,即在有向图中,存在通路能够与其相连;其次,这些对象是无用的,即程序之后不会再使用这些对象。这些对象不会被GC所回收,然而它却占用内存
CMSInitiatingOccupancyFraction <=((Xmx-Xmn)-(Xmn-Xmn/(SurvivorRatior+2)))/(Xmx-Xmn)*100
例如:
当xmx=128 xmn=36 SurvivorRatior=1时 CMSInitiatingOccupancyFraction<=((128.0-36)-(36-36/(1+2)))/(128-36)*100 =73.913
当xmx=128 xmn=24 SurvivorRatior=1时 CMSInitiatingOccupancyFraction<=((128.0-24)-(24-24/(1+2)))/(128-24)*100=84.615…
当xmx=3000 xmn=600 SurvivorRatior=1时 CMSInitiatingOccupancyFraction<=((3000.0-600)-(600-600/(1+2)))/(3000-600)*100=83.33
CMSInitiatingOccupancyFraction低于70% 须要调整xmn或SurvivorRatior值。
(8000-3000)-(3000-3000/3)/(8000-3000)*100=60
(4000-1500)-(1500-1500/3)/(4000-1500)*100=60
我本身的一个配置:
$JAVA_ARGS
.=
"
-Dresin.home=$SERVER_ROOT
-server
-Xmx8000M
-Xms8000M
-Xmn3000M
-XX:PermSize=500M
-XX:MaxPermSize=500M
-Xss1024K
-XX:+DisableExplicitGC
-XX:SurvivorRatio=1
-XX:+UseConcMarkSweepGC
-XX:+UseParNewGC
-XX:+CMSParallelRemarkEnabled
-XX:+UseCMSCompactAtFullCollection
-XX:CMSFullGCsBeforeCompaction=0
-XX:+CMSClassUnloadingEnabled
-XX:LargePageSizeInBytes=128M
-XX:+UseFastAccessorMethods
-XX:+UseCMSInitiatingOccupancyOnly
-XX:CMSInitiatingOccupancyFraction=55
-XX:SoftRefLRUPolicyMSPerMB=0
-XX:+PrintClassHistogram
-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps
-XX:+PrintHeapAtGC
-Xloggc:log/gc.log
";
使用这个配置之后,在GC日志中没有发现任何Full GC,因此网站不会有较大的停顿,可是使用jstat -gc 发现full gc 次数仍是有的,缘由是CMS GC,也就是对老年代的GC,也有显示在这里的FULL GC统计次数以内,不过CMS GC是并发低停顿的,因此对网站影响很是小,特别强调,CMS不是彻底没有停顿,是停顿的时间不多,缘由是:
这张图表示的是CMS在执行Full GC的过程,这个过程包括了6个步骤:
# STW initial mark
# Concurrent marking
# Concurrent precleaning
# STW remark
# Concurrent sweeping
# Concurrent reset
在这六个步骤中,有两个步骤须要STW,分别是:initial mark和remark(如图所示)。而其它的四个步骤是能够和application“并发”执行,因此也就2个步骤会暂停应用服务,因此就减小了服务暂停的时间