java服务启动的时候,都会指定一些参数,下面是一个典型的例子,我们来看一下这些参数都有什么作用
``` shell
JAVA_MEM_OPTS=" -server -Xmx2g -Xms2g -Xmn256m -XX:PermSize=128m -Xss256k -XX:+DisableExplicitGC -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:LargePageSizeInBytes=128m -XX:+UseFastAccessorMethods -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70
```
上面的参数设置分类两类:
1. `-X`开头
2. `-XX`开头
两者的区别是:`-X`开头的参数都是非标准参数,不能保证被所有的JVM虚拟机实现都支持。`-XX`开头的参数是不稳定的。
官方说明如下:
> Options that begin with -X are non-standard (not guaranteed to be supported on all VM implementations), and are subject to change without notice in subsequent releases of the JDK.
Options that are specified with -XX are not stable and are subject to change without notice.
`-XX`参数格式:
1. 布尔类型参数,通过`-XX:+`开启(即设为true),通过`-XX:-`关闭。
2. 数值类型参数,通过` -XX:=`设置,``中可以包含m(MB),k(KB)或者g(GB)
3. 字符串类型参数,通过`-XX:=`设置,通常可以用来设置文件名称,路径或者命令列表。
`-server` 表示java程序以server模式启动
`-Xmx2g` 堆最大大小为2G
`-Xms2g` 堆的初始大小为2G
`-Xmn256m` 设置年轻代大小为256M。整个JVM内存大小=年轻代大小 + 年老代大小 + 持久代大小。
`-Xss256k` 设置每个线程的堆栈大小。JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K。更具应用的线程所需内存大小进行调整。在相同物理内存下,减小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是有限制的,不能无限生成
`-XX:PermSize=128m` 设置持久代大小为128m。
`-XX:+DisableExplicitGC`: 禁用显式垃圾回收。如果设置了该选项,如果我们在程序中调用了`System.gc()`来进行垃圾回收,那么这个方法将成为一个空调用。
在Netty中的DirectBuffer会直接在堆内存以外分配内存,当空间不足的时候,就会显式调用`System.gc()`来腾出空间,此时如果我们设置了该选项,那么该功能将失效。具体参见[这里](http://blog.sina.com.cn/s/blog_6940cab30101ghgj.html)和[这里](http://iamzhongyong.iteye.com/blog/1743718)。
`-XX:+UseConcMarkSweepGC`: 对于老年代,使用并发的标记清除垃圾回收算法。
`-XX:+CMSParallelRemarkEnabled`: 降低标记停顿
`-XX:+UseCMSCompactAtFullCollection`:在FULL GC的时候,对老年代进行压缩。由于标记清除算法会导致大量内存碎片,所以压缩可以更好整理内存空间。
`-XX:LargePageSizeInBytes=128m`: 指定 Java heap 的分页页面大小
`-XX:+UseFastAccessorMethods`:
`-XX:+UseCMSInitiatingOccupancyOnly`:
我们用-XX+UseCMSInitiatingOccupancyOnly标志来命令JVM不基于运行时收集的数据来启动CMS垃圾收集周期。而是,当该标志被开启时,JVM通过CMSInitiatingOccupancyFraction的值进行每一次CMS收集,而不仅仅是第一次。然而,请记住大多数情况下,JVM比我们自己能作出更好的垃圾收集决策。因此,只有当我们充足的理由(比如测试)并且对应用程序产生的对象的生命周期有深刻的认知时,才应该使用该标志。
`-XX:CMSInitiatingOccupancyFraction=70 `:
当堆满之后,并行收集器便开始进行垃圾收集,例如,当没有足够的空间来容纳新分配或提升的对象。对于CMS收集器,长时间等待是不可取的,因为在并发垃圾收集期间应用持续在运行(并且分配对象)。因此,为了在应用程序使用完内存之前完成垃圾收集周期,CMS收集器要比并行收集器更先启动。
因为不同的应用会有不同对象分配模式,JVM会收集实际的对象分配(和释放)的运行时数据,并且分析这些数据,来决定什么时候启动一次CMS垃圾收集周期。为了引导这一过程, JVM会在一开始执行CMS周期前作一些线索查找。该线索由 -XX:CMSInitiatingOccupancyFraction=来设置,该值代表老年代堆空间的使用率。比如,value=75意味着第一次CMS垃圾收集会在老年代被占用75%时被触发。通常CMSInitiatingOccupancyFraction的默认值为68(之前很长时间的经历来决定的)。
## 参考资料
官方文档1:http://www.oracle.com/technetwork/articles/java/vmoptions-jsp-140102.html
官方文档2:http://www.oracle.com/technetwork/java/tuning-139912.html
IFEVE:http://ifeve.com/useful-jvm-flags-part-7-cms-collector/
http://blog.sokolenko.me/2014/11/javavm-options-production.html
http://www.cnblogs.com/likehua/p/3369823.html
http://khaidoan.wikidot.com/java-performance-tuning