【JVM调优】JVM 参数说明 与 《元空间》

发布时间:2024年01月19日
  • -XX:+HeapDumpOnOutOfMemoryError?
    • dump堆内存溢出信息
  • XX:HeapDumpPath=/opt/app/applogs/68dump.hprof"
    • dump文件存储路径
  • -Xloggc:? /opt/app/applogs/gc.log
    • 打印gc日志,指定路径? ?
  • -Xms:
    • 初始化堆内存大小,默认为物理内存的1/64(小于1GB)。
  • -Xmx:
    • 堆内存最大值。**默认(MaxHeapFreeRatio参数可以调整)空余堆内存大于70%时,JVM会减少堆直到-Xms的最小限制。
  • -Xmn:
    • 新生代大小,包括Eden区与2个Survivor区。
  • -XX:
    • SurvivorRatio=1:Eden区与一个Survivor区比值为1:1。
  • -XX:
    • MaxDirectMemorySize=1G:**直接内存。**报java.lang.OutOfMemoryError: Direct buffer memory异常可以上调这个值。
  • -XX:
    • +DisableExplicitGC:禁止运行期显式地调用System.gc()来触发fulll GC。
  • 注意: Java RMI的定时GC触发机制可通过配置-Dsun.rmi.dgc.server.gcInterval=86400来控制触发的时间。
  • -XX:
    • CMSInitiatingOccupancyFraction=60:老年代内存回收阈值,默认值为68。
  • -XX:
    • ConcGCThreads=4:CMS垃圾回收器并行线程线,推荐值为CPU核心数。
  • -XX:
    • ParallelGCThreads=8:新生代并行收集器的线程数。
  • -XX:
    • MaxTenuringThreshold=10:**设置垃圾最大年龄。**如果设置为0的话,则年轻代对象不经过Survivor区,直接进入年老代。对于年老代比较多的应用,可以提高效率。如果将此值设置为一个较大值,则年轻代对象会在Survivor区进行多次复制,这样可以增加对象再年轻代的存活时间,增加在年轻代即被回收的概论。
  • -XX:
    • CMSFullGCsBeforeCompaction=4:指定进行多少次fullGC之后,进行tenured区 内存空间压缩。
  • -XX:
    • CMSMaxAbortablePrecleanTime=500:当abortable-preclean预清理阶段执行达到这个时间时就会结束。?????

遇到宕机等生产事故的时候,解决问题都不是通过一个日志来处理的,需要通过dump日志,gc日志还有jstack日志进行综合分析,才能更快的定位,解决问题

本人遇到的实际问题:

-XX:MetaspaceSize=1024m? 我们测试环境没有去设置这个参数配置,那默认就是21MB,21MB对于我们的系统来说是远远不够的,导致我们的测试环境老是突然挂掉,通过配置

export JAVA_OPTS="-Xms10240m -Xmx10240m -Xss2048K -XX:MetaspaceSize=1024m ?-Dcheck.global=true -Dhsts.filter=true

-DX-Frame-Options=true

-Dsecurity.disable=true

-Dfastjson.parser.safeMode=true -verbose:gc

-XX:+PrintGCDetails

-XX:+PrintGCDateStamps -Xloggc:/opt/app/applogs/gc.log

-XX:+HeapDumpOnOutOfMemoryError

-XX:HeapDumpPath=/opt/app/applogs/68dump.hprof"

打印gc日志,发现短时间内发生了八次full GC??

原因是因为-XX:MetaspaceSize=1024m 没配置,元空间的内存不足,导致一直fullGc

课外知识:

  1. JDK1.7 有永久代,字符串常量池,静态变量移除,保存在堆中 其他的常量池存放在永久代
  2. JDK1.8 无永久代,类型信息,字段,方法,常量保存在本地内存的元空间,但字符串常量池、静态变量仍然在堆中。

永久代为什么要被元空间替代?


只有Hotspot才有永久代。BEA JRockit、IBMJ9等来说,是不存在永久代的概念的

1.JDK8 开始 无永久代改为元空间,分配在本地内存中,元空间的最大可分配空间就是系统可用内存空间;

2.为永久代设置空间大小是很难确定的,在某些场景下,如果动态加载类过多,容易产生方法区的OOM。比如某个实际Web工程中,因为功能点比较多,需要加载的类很多,在运行过程中,要不断动态加载很多类,经常出现致命错误。 java.lang.OutOfMemoryError:PermGen space

3.而元空间和永久代之间最大的区别在于:元空间并不在虚拟机中,而是使用本地内存。因此,默认情况下,元空间的大小仅受本地内存限制。

总结:

  1. 没有设置元空间大小,默认了初始值,导致频繁fullGC,测试环境在启服务的时候每次都很慢
  2. 新生代空间越大,Minor GC的GC时间越长,频率越低。如果想减少其持续时长,就需要减少其空间大小
  3. ?jmap -dump:format=b,file=xxx pid,可以生成堆信息的文件,但是这个命令不建议在生产环境使用,因为当内存较大时,执行该命令会占用大量系统资源,甚至造成卡顿。建议在项目启动时添加下面的命令,在发生oom时自动生成堆信息文件:-XX:+HeapDumpOnOutOfMemory。
文章来源:https://blog.csdn.net/weixin_47188125/article/details/135680643
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。