一、常见的JVM参数配置:

1、垃圾回收统计信息

-XX:+PrintGC     打印GC简要信息

-XX:+PrintGCDetails打印GC的详细信息

-XX:+PrintGCTimeStamps打印CG发生的时间戳

-Xloggc:log/gc.log 指定GC log的位置,以文件输出

-XX:+PrintHeapAtGC 每一次GC前和GC后,都打印堆信息。

2、堆设置

-Xms:初始堆大,最小堆

-Xmx:最大堆大小

-Xmn:设置新生代的大小

-XX:NewRatio新生代和年老代的比值,如为3,表示年轻代与年老代比值为1:3,年轻代占整个年轻代年老代之和的1/4

-XX:SurvivorRatio设置两个Survivor区和eden的比值。注意Survivor区有两个。如:8,表示Eden:Survivor=8:2,一个Survivor区占整个年轻代的1/10

-XX:PermSize:设置永久区的初始空间

-XX:MaxPermSize:设置永久区的最大空间。

-XX:+MaxTenuringThreshold=10:新生代垃圾的最大年龄,代表对象在Survivor区经过10次复制以后才进入老年代。如果设置为0,则年轻代对象不经过Survivor区,直接进入老年代。

-XX:+PretenureSizeThreshold:设置大对象直接进入老年代的阈值。当对象的大小超过这个值时,将直接在老年代分配。

3、栈的分配参数:

-Xss:设置栈空间的大小。

4、垃圾收集器设置

(1)串行收集器的设置:

-XX:+UseSerialGC:设置串行收集器,一般适用于小型应用和单处理器,算法比较简单,GC效率也较高,但可能会给应用带来停顿。

(2)并行回收收集器设置(ParallelGC收集器的目标是达到一个可控制的吞吐量)

-XX:+UseParNewGC:设置年轻代为并行收集。

-XX:+UseParallelGC:设置年轻代使用并行回收收集器。多个线程并行执行GC,一般适用于多处理器系统中,可以提高GC的效率,但算法复杂,系统消耗较大。

-XX:+UseParalledlOldGC:设置老年代为并行回收收集器,Java1.6之后才出现。

-XX:ParallelGCThreads=n:设置并行收集器收集时使用的线程数,最好与CPU数目相等。

-XX:MaxGCPauseMillis=n:设置年轻代每次并行垃圾回收的最大暂停时间。

-XX:GCTimeRatio=n:设置垃圾回收时间占程序运行时间的百分比。公式为1/(1+n)

-XX:+UseAdaptiveSizePolicy:自适应策略,自动选择年轻代区大小和相应的Survivor区比例。

(3)CMS并发收集器:(以最短停顿为目标)

-XX:+UseConcMarkSweepGC:使用CMS内存收集。

-XX:+ParallelCMSThreads: 设定 CMS 的线程数量。

-XX:CMSFullGCsBeforeCompaction:CMS多少次后进行内存压缩,由于并发收集器不对内存空间进行压缩整理,所以运行一段时间以后会产生"碎片",使得运行效率降低。

-XX:+UseCMSCompactAtFullCollection:在FULL GC的时候,对年老代的压缩。CMS是不会移动内存的,因此,这个非常容易产生碎片,导致内存不够用,因此,内存的压缩这个时候就会被启用。可能会影响性能,但是可以消除碎片。

-XX:+CMSInitiatingOccupancyFraction:设置 CMS 收集器在老年代空间被使用多少后触发,默认为 68%。

-XX:+CMSClassUnloadingEnabled:允许对类元数据进行回收。

-XX:+CMSParallelRemarkEndable:启用并行重标记。

-XX:CMSInitatingPermOccupancyFraction:当永久区占用率达到这一百分比后,启动 CMS 回收 (前提是-XX:+CMSClassUnloadingEnabled 激活了)。

-XX:UseCMSInitatingOccupancyOnly:表示只在到达阈值的时候,才进行 CMS 回收。

-XX:+CMSIncrementalMode:使用增量模式,比较适合单 CPU。

(4)G1收集器:

-XX:+UseG1GC:使用 G1 回收器。

-XX:+UnlockExperimentalVMOptions:允许使用实验性参数。

-XX:+MaxGCPauseMills:设置最大垃圾收集停顿时间。

-XX:+GCPauseIntervalMills:设置停顿间隔时间。

更多参数的详细介绍和设置可以参考这篇博客:https://www.cnblogs.com/redcreen/archive/2011/05/04/2037057.html

二、JVM的GC性能优化:

对于GC的性能主要有2个方面的指标:吞吐量(工作时间不算,gc的时间占总的时间比)和暂停时间。

1. 堆大小:

默认情况下,vm会增加/减少heap大小以维持free space在整个vm中占的比例,这个比例由MinHeapFreeRatio和MaxHeapFreeRatio指定。

一般而言,server端的app会有以下规则:

(1)对vm分配尽可能多的内存;

(2)将Xms和Xmx设为一样的值。如果虚拟机启动时设置使用的内存比较小,这个时候又需要初始化很多对象,虚拟机就必须重复地增加内存。

(3)处理器核数增加,内存也跟着增大。

2. 年轻代:

(1)对于程序流畅性运行影响的因素是新生代的大小。新生代越大,minor collection越少;但是在堆大小固定情况下,新生代越大就意味着越小的老年代,就意味着更多的major collection。

(2)NewRatio反映的是新生代和老年代的大小比例。NewSize和MaxNewSize反映的是young generation大小的下限和上限,将这两个值设为一样就固定了young generation的大小(同Xms和Xmx设为一样)。

(3)SurvivorRatio也可以优化survivor的大小,不过这对于性能的影响不是很大。SurvivorRatio是Eden和Survior大小比例。

一般而言,server端的app会有以下规则:

(1)首先决定能分配给vm的最大的堆大小,然后设定最佳的young generation的大小;

(2)如果堆大小固定后,增加新生代的大小意味着减小老年代大小。让老年代在任何时候够大,能够容纳所有存活的对象(留10%-20%的空余)。

3、年轻代大小选择

(1)响应时间优先的应用:尽可能设大,直到接近系统的最低响应时间限制,在此种情况下,年轻代收集发生的频率也是最小的,同时,减少到达年老代的对象。

(2)吞吐量优先的应用:尽可能的设置大,可能到达Gbit的程度,因为对响应时间没有要求,垃圾收集可以并行进行,一般适合8CPU以上的应用。

(3)避免设置过小。当新生代设置过小时会导致:①YGC次数更加频繁;②可能导致YGC对象直接进入旧生代,如果此时旧生代满了,会触发FGC。

4、年老代大小选择

(1)响应时间优先的应用:年老代使用并发收集器。如果堆设置小了,可以会造成内存碎片、高回收频率以及应用暂停而使用传统的标记清除方式;如果堆大了,则需要较长的收集时间。一般需要参考以下数据:

并发垃圾收集信息、持久代并发收集次数、传统GC信息、花在年轻代和年老代回收上的时间比例。

(2)吞吐量优先的应用:一般吞吐量优先的应用都有一个很大的年轻代和一个较小的年老代,这样可以尽可能回收掉大部分短期对象,减少中期的对象,而年老代尽存放长期存活对象。

5、较小堆引起的碎片问题
因为CMS年老代的并发收集器使用标记清除算法所以不会对堆进行压缩当收集器回收时,他会把相邻的空间进行合并,这样可以分配给较大的对象。但是,当堆空间较小时,运行一段时间以后,就会出现"碎片",如果并发收集器找不到足够的空间,那么并发收集器将会停止,可能需要进行如下配置:
-XX:+UseCMSCompactAtFullCollection:使用并发收集器时,开启对年老代的压缩。
-XX:CMSFullGCsBeforeCompaction=0:上面配置开启的情况下,这里设置多少次Full GC后,对年老代进行压缩。

4、用64位操作系统,Linux下64位的jdk比32位jdk要慢一些,但是吃得内存更多,吞吐量更大。

5、XMX和XMS设置一样大,MaxPermSize和MinPermSize设置一样大,这样可以减轻伸缩堆大小带来的压力

6、CMS的目标是最短的GC停顿时间,使用CMS的好处是用尽量少的新生代,然后老生代利用CMS并行收集,这样能保证系统低延迟的吞吐效率。

7、系统停顿的时候可能是GC的问题也可能是程序的问题,多用jmap和jstack查看,或者killall -3 java,然后查看java控制台日志,能看出很多问题。

8、如果用了缓存,那么年老代应该大一些,缓存的HashMap不应该无限制长,建议采用LRU算法的Map做缓存,LRUMap的最大长度也要根据实际情况设定。

9、采用并发回收时,年轻代小一点,年老代要大,因为年老代用的是并发回收,即使时间长点也不会影响其他程序继续运行,网站不会停顿。

10、JVM参数的设置(特别是 –Xmx –Xms –Xmn -XX:SurvivorRatio  -XX:MaxTenuringThreshold等参数的设置)没有一个固定的公式,需要根据PV old区实际数据、YGC次数等多方面来衡量。为了避免promotion faild可能会导致xmn设置偏小,也意味着YGC的次数会增多,处理并发访问的能力下降等问题。每个参数的调整都需要经过详细的性能测试,才能找到特定应用的最佳配置。

promotion failed:(晋升失败)

垃圾回收时promotion failed,一般可能是两种原因产生,第一个原因是To survivor救助空间不够,救助空间里的对象还不应该被移动到年老代,但年轻代又有很多对象需要放入救助空间;第二个原因是年老代没有足够的空间接纳来自年轻代的对象;这两种情况都会转向Full GC,网站停顿时间较长。

解决方案:

第一个原因解决办法是去掉救助空间,设置-XX:SurvivorRatio=65536 -XX:MaxTenuringThreshold=0即可,但是因为没有用到救助空间,所以年老代容易满,Full GC执行会比较频繁,所以可以把救助空间加大,这样也不会有promotion failed。

第二个原因我的解决办法是设置CMSInitiatingOccupancyFraction为某个值(假设70),这样年老代空间到70%时就开始执行CMS,年老代有足够的空间接纳来自年轻代的对象。

11、实际编程中的性能优化:

下面是一些在实际写程序的过程中应该注意的点:养成这些习惯可以在一定程度上减少内存的无谓消耗,进一步就可以减少因为内存不足导致GC不断。参考自:https://blog.csdn.net/antony9118/article/details/51375662

(1)减少new对象。每次new对象之后,都要开辟新的内存空间。这些对象不被引用之后,还要回收掉。因此,如果最大限度地合理重用对象,或者使用基本数据类型替代对象,都有助于节省内存;

(2)多使用局部变量,减少使用静态变量。局部变量被创建在栈中,存取速度快。静态变量则是在堆内存;

(3)避免使用finalize,该方法会给GC增添很大的负担;

(4)如果是单线程,尽量使用非多线程安全的,因为线程安全来自于同步机制,同步机制会降低性能。例如,单线程程序,能使用HashMap,就不要用HashTable。同理,尽量减少使用synchronized

(5)用移位符号替代乘除号。eg:a*8应该写作a<<3

(6)对于经常反复使用的对象使用缓存;

(7)尽量使用基本类型而不是包装类型,尽量使用一维数组而不是二维数组;

(8)尽量使用final修饰符,final表示不可修改,访问效率高;

(9)单线程情况下(或者是针对于局部变量),字符串尽量使用StringBuilder,比StringBuffer要快;

(10)String为什么慢?因为String 是不可变的对象, 因此在每次对 String 类型进行改变的时候其实都等同于生成了一个新的 String 对象,然后将指针指向新的 String 对象。如果不能保证线程安全,尽量使用StringBuffer来连接字符串。这里需要注意的是,StringBuffer的默认缓存容量是16个字符,如果超过16,apend方法调用私有的expandCapacity()方法,来保证足够的缓存容量。因此,如果可以预设StringBuffer的容量,避免append再去扩展容量。如果可以保证线程安全,就是用StringBuilder。

Java虚拟机:常见JVM参数配置和GC性能优化相关推荐

  1. 12.JDK1.8 JVM运行时数据区域概览、各区域介绍、程序计数器、Java虚拟机栈、本地方法栈、堆、堆空间内存分配(默认情况下)、字符串常量池、元数据区、jvm参数配置

    12.JDK1.8 JVM运行时数据区域概览 12.1.JDK1.8 JVM运行时数据区域概览 12.2.各区域介绍 12.3.各区域介绍 12.3.1.程序计数器 12.3.2.Java虚拟机栈 1 ...

  2. java虚拟机在哪配置参数,Java虚拟机(JVM)参数配置说明

    Java虚拟机(JVM)参数配置说明 1. Java VM 运行于linux平台上的JVM会读取/etc/sysconfig/i18n中的参数来决定输出流的编码方式,如果在安装linux系统过程中没有 ...

  3. Java虚拟机(JVM)参数配置说明

    http://lavasoft.blog.51cto.com/62575/25492/ Java虚拟机(JVM)参数配置说明   在Java.J2EE大型应用中,JVM非标准参数的配置直接关系到整个系 ...

  4. kafka java jvm 优化_kafka优化–JVM参数配置优化

    主要是启动脚本和log4j基本参数的设置和优化,这些参数藏的比较深. 1.JVM参数配置优化 如果使用的CMS GC算法,建议JVM Heap不要太大,在4GB以内就可以.JVM太大,导致Major ...

  5. 【Flink】Flink jvm参数配置GC日志

    1.概述 转载:Flink jvm参数配置GC日志 生产环境上,或者其他要测试 GC 问题的环境上,一定会配置上打印GC日志的参数,便于分析 GC 相关的问题. 但是可能很多人配置的都不够" ...

  6. 【2022最新Java面试宝典】—— Java虚拟机(JVM)面试题(51道含答案)

    目录 一.Java内存模型 1. 我们开发人员编写的Java代码是怎么让电脑认识的 2. 为什么说java是跨平台语言 3. Jdk和Jre和JVM的区别 4. 说一下 JVM由那些部分组成,运行流程 ...

  7. 【Java书笔记】:《深入理解Java虚拟机:JVM高级特性与最佳实践(第3版)》第2部分-自动内存管理,第3部分-虚拟机执行子系统,第5部分-高效并发

    作者:周志明 整理者GitHub:https://github.com/starjuly/UnderstandingTheJVM 第2部分-自动内存管理 第2章 Java内存区域与内存溢出异常 2.2 ...

  8. 读书笔记之《深入理解Java虚拟机:JVM高级特性与最佳实践》

    本篇带来的是周志明老师编写的<深入理解Java虚拟机:JVM高级特性与最佳实践>,十分硬核! 全书共分为 5 部分,围绕内存管理.执行子系统.程序编译与优化.高效并发等核心主题对JVM进行 ...

  9. 深入理解Java虚拟机:JVM高级特性与最佳实践(第3版)读书笔记

    前言 我在读 深入理解java虚拟机 这本书,把整体其中的关键点标记了,希望自己对它有个不一样的理解,也希望大家能看看这本写的很好的书 深入理解Java虚拟机:JVM高级特性与最佳实践(第3版) pd ...

最新文章

  1. 佐治亚理工学院发文:不要迷信可解释性,小心被误导
  2. 会计的思考(6):阳光是最好的杀虫剂—会计反映
  3. Android HttpClient GET或者POST请求基本使用方法
  4. Python实训day07pm【Selenium操作网页、爬取数据-下载歌曲】
  5. HDU - 6975 Forgiving Matching FFT匹配字符串
  6. 【渝粤教育】广东开放大学 国际金融 形成性考核 (48)
  7. mac中一一些常用的命令
  8. Linux安装与配置
  9. 如何linux网页修改回80端口,linux下如何修改iptables开启80端口
  10. C++异常处理全攻略
  11. 2020过去了,我们想给那些病毒和劫持软件颁个奖……
  12. 先锋linux 64位安装包的安装使用
  13. python +appium实现原理_Appium工作原理
  14. RELYUM—针对关键系统的物联网和网络安全解决方案 (一)
  15. 微软远程桌面mac/ios/android客户端
  16. python 概率分布模型_使用python的概率模型进行公司估值
  17. Downloads Help 下载帮助
  18. Python 自动化办公
  19. Python解决图文验证码登录识别(1)
  20. python自然语言处理 |分析句子的意思

热门文章

  1. 在 Python 中使用 OpenCV 高斯模糊我这张的丑脸
  2. 六、Go编程语言中的函数式编程
  3. tornado设置cookie和seesion
  4. textrank4zh来处理句子的重要度
  5. 光速OFFER,为AI奔赴,商汤2022届校招提前批正式启动!
  6. 独立艺术家大谷spizher带你玩转PaddleGAN
  7. 天池大赛通用目标检测的对抗攻击方法一览
  8. Google、Stanford导师带出的AI人才,是你吗?
  9. 丑憨批的爬虫笔记2(爬虫引发的问题+robots协议)
  10. HDU 1874 SPFA算法Dijkstra算法