JVM 参数怎么调

基于 JVM 的语言和应用程序汗牛充栋,不仅限于 Java , 还有 Scala , JPython, JRuby。对于 JVM 的调优是每个JVM 应用开发者必需要了解的。

先回顾一下 JVM 的结构

JVM 结构

JVM structure

堆内部的分代

  • 年轻代 Young Generation: 一般分为伊甸园 Eden 和幸存区 Survivor(通过分为两个区S0, S1), 新创建的对象放在Eden 区
  • 年老代 Old Generation
  • 永久代 Permanent Generation, Java 8 中改为 MetaSpace
JVM Heap

JVM 参数调优

JVM 参数既多且杂,如何提纲挈领,避免挂一漏万呢?个人的想法是掌握原理,了解常用的参数就好了,以度量来驱动适用于你的应用程序的参数设置。

  • 1)设计:
    分析你的应用程序要求的吞吐量如何,它对于短暂的停顿是否敏感,从而了解到大约需要多大的内存,从而设置一个比较合理的参数,例如
    -Xms2048m
    -Xmx2048m
    -XX:MetaspaceSize=128m
    -XX:MaxMetaspaceSize=256m
    -XX:CompressedClassSpaceSize=256m
    -Xss1m
  • 2) 运行
    在程序运行期间设置如下参数来打印 GC 的运行时信息
-XX:+PrintGCDetails 
-XX:+PrintGCDateStamps 
-XX:+PrintHeapAtGC 
-XX:+PrintTenuringDistribution 
-XX:+PrintGCApplicationStoppedTime 
-XX:+PrintPromotionFailure 
-XX:+UseGCLogFileRotation 
-XX:NumberOfGCLogFiles=10 
-XX:GCLogFileSize=10M 
-Xloggc:./bin/../logs/gc.log
-XX:OnOutOfMemoryError="sh ./bin/oom-hander.sh"
  • 3) 监控
    重点监控如下指标

    • heap 堆内存使用情况
    • non-heap 非堆内存使用情况
    • gc pause 垃圾回收信息
    • oom 内存溢出错误
    • stackOverFlow 栈溢出错
  • 4)调优
    调整参数,以期更合理的内存分配和垃圾回收

目的: 尽量减少停顿时间,释放出更多可用内存

常用JVM 调优参数

Java 命令行选项一般分为三类

  1. 标准选项:
    例如:
-client
-server
  1. 非标准选项
    以 -X 为前缀
    例如:
-Xms1024m
-Xmx1024m
-Xss1m
  1. 非稳定选项
    以 -XX 为前缀
-XX:CompressedClassSpaceSize=256m
-XX:MetaspaceSize=64m
-XX:MaxMetaspaceSize=128m
  • JVM内存与垃圾收集
    • GC分类:
      • Minor GC
        • 也称 Scavenge GC, 收集新生代
        • 新对象在 Eden区申请空间失败时会触发
      • Major GC
        • 也称 Full GC, 收集新生代,年老代和永久代
        • 年老代或永久代被写满时会触发
    • GC算法:
      • 引用计数 Reference Counting
      • 标记清除 Mark-Sweep
      • 复制 Copying
      • 标记-压缩 Mark-Compact
    • JVM参数:
      • -Xmx=2048m 堆的最大值
      • -Xms=1024m 堆的初始值
      • -Xmn=128m 年轻代大小的值
      • -XX:newSize= 年轻代大小的初始值
      • -XX:maxNewSize= 年轻代大小的最大值
      • -XX:NewRatio= 年轻代与年老代的比例=年老代大小/年轻代大小
      • -XX:SurvivorRatio= 年轻代中的 Eden 区与 Survivor 区的比例=Eden区大小/(S1或S2区的大小)
      • -XX:MetaSpaceSize= 元空间(永久代)大小的初始值
      • -XX:MaxMetaSpaceSize= 元空间(永久代)大小的最大值
      • -Xss: 每个线程的堆栈大小
      • -XX:MaxDirectMemorySize= 直接内存大小的最大值
      • -XX:CompressedClassSpaceSize= 堆在小于32G时会将类信息放入 CompressedClassSpace, 即地址将64bit压缩成32bit
      • -XX:+AlwaysPreTouch 启动时预先初始化内存页,这样运行期就省去了初始化内存页这个步骤了
    • 指标
      • Throughput 吞吐量
        • the percentage of total time not spent in GC considered over long periods of time
      • Pauses 暂停时间
        • the times when an application appears unresponsive because GC is occurring
    • 分代 Generations 及适应的参数和回收算法
      • 永久代(元数据空间) MetaSpace
        • -XX:MetaspaceSize=128m
          • the initial amount of space(the initial high-water-mark)
        • -XX:MaxMetaspaceSize=256m
          • the maximum amount of space to be allocated for class metadata
        • -XX:MinMetaspaceFreeRatio=
          • min high-water-mark
        • -XX:MaxMetaspaceFreeRatio=
          • max high-water-mark
      • 年轻代 Young Generation
        • Serial
          • -XX:+UseSerialGC
        • ParNew
          • -XX:+UseParNew
        • Parallel Scavenge
          • -XX:+UseParallelGC
          • -XX:ParallelGCThreads=
      • 年老代 Old Generation
        • Serial Old
        • Parallel Old
        • CMS(Concurrent Mark Sweep)
          • -XX:+UseConcMarkSweepGC
        • G1(Gargage First)
          • -XX:+UseG1GC
          • -XX:MaxGCPaouseMillis=
          • -XX:ParallelGChreads=
    • Behavior-BasedTuning
      • 暂停时间目标 Pause Time Goal
        • -XX:MaxGCPauseMillis=
      • 吞吐量目标Throughput Goal
        • -XX:GCTimeRatio=
          • -XX:GCTimeRatio=19 sets a goal of 1/20th or 5% of the total time for GC
      • 体积目标 Footprint Goal
        • reduces the size of the heap until one of the goals(invariably the throughput goal) cannot be met
    • 调优策略 Tuning Strategy
      • 选择适合你的应用程序的吞吐量目标.
      • 选择适合的暂停时间目标,这点要和上面的吞吐量目标可能有冲突,要根据你的需要做出平衡

实例

以 Cassandra 为例,它是的一个高性能的分布式NOSQL 数据存储系统,它设置了如下 JVM 参数:

bin/java -Xloggc:./bin/../logs/gc.log 
-ea 
-XX:+UseThreadPriorities 
-XX:ThreadPriorityPolicy=42 
-XX:+HeapDumpOnOutOfMemoryError 
-Xss256k 
-XX:StringTableSize=1000003 
-XX:+AlwaysPreTouch 
-XX:-UseBiasedLocking 
-XX:+UseTLAB 
-XX:+ResizeTLAB 
-XX:+UseNUMA 
-XX:+PerfDisableSharedMem 
-Djava.net.preferIPv4Stack=true 
-XX:+UseParNewGC 
-XX:+UseConcMarkSweepGC 
-XX:+CMSParallelRemarkEnabled 
-XX:SurvivorRatio=8 
-XX:MaxTenuringThreshold=1 
-XX:CMSInitiatingOccupancyFraction=75 
-XX:+UseCMSInitiatingOccupancyOnly 
-XX:CMSWaitDuration=10000 
-XX:+CMSParallelInitialMarkEnabled 
-XX:+CMSEdenChunksRecordAlways 
-XX:+CMSClassUnloadingEnabled 
-XX:+PrintGCDetails 
-XX:+PrintGCDateStamps 
-XX:+PrintHeapAtGC 
-XX:+PrintTenuringDistribution 
-XX:+PrintGCApplicationStoppedTime 
-XX:+PrintPromotionFailure -XX:+UseGCLogFileRotation 
-XX:NumberOfGCLogFiles=10 
-XX:GCLogFileSize=10M 
-Xms4096M 
-Xmx4096M 
-Xmn800M 
-XX:+UseCondCardMark 
-XX:CompileCommandFile=./bin/../conf/hotspot_compiler 
-javaagent:./bin/../lib/jamm-0.3.0.jar 
-Dcassandra.jmx.local.port=7199 
-Dcom.sun.management.jmxremote.authenticate=false 
-Dcom.sun.management.jmxremote.password.file=/etc/cassandra/jmxremote.password 
-Djava.library.path=./bin/../lib/sigar-bin 
-XX:OnOutOfMemoryError=kill -9 %p 
-Dlogback.configurationFile=logback.xml 
-Dcassandra.logdir=./bin/../logs 
-Dcassandra.storagedir=./bin/../data 
-Dcassandra-foreground=yes 
-cp ./bin/../conf:./bin/../build/classes/main:./bin/../build/classes/thrift:...jar: org.apache.cassandra.service.CassandraDaemon

监控与观察

一般来说,比较常用的方法是通过 JMX 和 GC log 来度量你的 JVM 参数设置是是否合理,一旦发现异常或者 OOM 要马上采取措施进行调整

jstat -gcutil 1324
  S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT
  0.00   0.00  15.10   7.84  97.24  92.57      2       0.017     1      0.034    0.051
  • S0: Survivor space 0 生存空间0利用率占该空间当前容量的百分比
  • S1: Survivor space 1 幸存者空间1利用率占该空间当前容量的百分比
  • E: Eden space 伊甸园空间利用率占空间当前容量的百分比
  • O: Old space 旧空间利用率占空间当前容量的百分比
  • M: Metaspace 元空间利用率占空间当前容量的百分比
  • CCS: Compressed class space 压缩的类空间利用率(以百分比表示)
  • YGC: Young generation GC 年轻代GC次数.
  • YGCT: Young generation GC Time年轻代GC耗时
  • FGC: Full GC 完全GC次数
  • FGCT: Full GC Time 完全GC耗时
  • GCT: Total GC Time 总GC耗时

关于 JVM 内存溢出的分析可以参考以前写的 内存溢出不可怕,手足无措才尴尬

参考资料

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269