Java能力框架之JVM调优

操作系统级别Java进程所占用的内存数值不能准确的反应堆内存的真实占用情况,因为GC过后这个值是不会变化的,内存调优的时候要更多地使用JDK提供的内存查看工具,比如JConsole和Java VisualVM。

Full GC

Full GC的几种情况

对JVM内存的系统级的调优主要的目的是减少GC的频率和Full GC的次数,过多的GC和Full GC是会占用很多的系统资源(主要是CPU),影响系统的吞吐量。特别要关注Full GC,因为它会对整个堆进行整理,导致Full GC一般由于以下几种情况:

  • 旧生代空间不足 调优时尽量让对象在新生代GC时被回收、让对象在新生代多存活一段时间和不要创建过大的对象及数组避免直接在旧生代创建对象。

  • Pemanet Generation空间不足

  • 增大Perm Gen空间,避免太多静态对象

  • 统计得到的GC后晋升到旧生代的平均大小大于旧生代剩余空间

  • 控制好新生代和旧生代的比例

  • System.gc()被显示调用

  • 垃圾回收不要手动触发,尽量依靠JVM自身的机制

调优比例不良设置会导致的后果

调优手段主要是通过控制堆内存的各个部分的比例和GC策略来实现,下面来看看各部分比例不良设置会导致什么后果。

新生代设置过小,有以下两种情况

  • 会让新生代GC次数非常频繁,增大系统消耗;
  • 会导致大对象直接进入旧生代,占据了旧生代剩余空间,诱发Full GC。

新生代设置过大,有以下两种情况

  • 会导致旧生代过小(堆总量一定),从而诱发Full GC;
  • 新生代GC耗时大幅度增加,一般说来新生代占整个堆1/3比较合适;

Survivor设置过小

导致对象从eden直接到达旧生代,降低了在新生代的存活时间。

Survivor设置过大

导致eden过小,增加了GC频率。

调优策略

由内存管理和垃圾回收可知新生代和旧生代都有多种GC策略和组合搭配,选择这些策略对于我们这些开发人员是个难题,JVM提供两种较为简单的GC策略的设置方式:

吞吐量优先

JVM以吞吐量为指标,自行选择相应的GC策略及控制新生代与旧生代的大小比例,来达到吞吐量指标。这个值可由-XX:GCTimeRatio=n来设置

暂停时间优先

JVM以暂停时间为指标,自行选择相应的GC策略及控制新生代与旧生代的大小比例,尽量保证每次GC造成的应用停止时间都在指定的数值范围内完成。这个值可由-XX:MaxGCPauseRatio=n来设置。

JVM参数设置

堆内存

  • -Xms: 或-XX:InitialHeapSize,最小堆内存,单位是Byte,m,g等
  • -Xmx:或 -XX:MaxHeapSize,最大堆内存,单位是Byte,m,g等 比如java -Xms128m -Xmx2g

新生代

-XX:NewSize

初始时年轻区内存,通常为 Xmx 的 1/3 或 1/4。

-XX:MaxNewSize

最大年轻区内存

-XX:MaxTenuringThreshold

来控制新生代存活时间,尽量让对象在新生代被回收。 新生代=Eden + 2 个 Survivor空间, 但实际可用空间为 = Eden + 1 个 Survivor,即 90%。

新老比值变化

-XX:NewRatio

指定老年代与新生代的堆大小比例。在使用CMS收集器时,此参数失效

-XX:SurvivorRatio

新生代中 Eden 与 Survivor 的比值。默认值为 8,即 Eden 占新生代空间的 8/10,另外两个 Survivor 各占 1/10。

--MinHeapFreeRatio

指定jvm heap在使用率小于所设定的值,heap进行收缩,Xmx==Xms的情况下无效

-XX:MaxHeapFreeRatio

指定jvm heap在使用率大于n的情况下,heap进行扩张,Xmx==Xms的情况下无效

线程栈

  • -Xss:线程栈大小

Java heap页大小

  • -XX:LargePageSizeInBytes:指定Java heap的分页页面大小

压缩类指针

  • -XX:+UseCompressedClassPointers

    压缩类指针。对象的类指针(_klass)被压缩至32bit,使用类指针压缩空间的基地址

  • -UseCompressedOops

    压缩对象指针,oops是普通对象指针,Java堆中对象的对象指针被压缩到32bit,使用堆基地址。

注意:64bit的服务器上设置-Xmx32g时,-XX:+UseCompressedOops和-XX:+UseCompressedClassPointers会失效,所以最大的堆设置为31g

永久代(jdk8以前)

  • -XX:PermSize 永久代初始大小
  • -XX:MaxPermSize:永久代大小的最大值

元数据相关(jdk8及以后)

-XX:MetaspaceSize

初始空间大小,达到该值就会触发垃圾收集进行类型卸载。

-XX:MaxMetaspaceSize

最大空间,默认是没有限制的。

-XX:MinMetaspaceFreeRatio

在GC之后,最小的Metaspace剩余空间容量的百分比,减少为分配空间所导致的垃圾收集

-XX:MaxMetaspaceFreeRatio

在GC之后,最大的Metaspace剩余空间容量的百分比,减少为释放空间所导致的垃圾收集

-XX:MaxMetaspaceExpansion

Metaspace增长时的最大幅度

XX:MinMetaspaceExpansion

Metaspace增长时的最小幅度

垃圾回收统计信息

  • -XX:+PrintGC
  • -XX:+PrintGCDetails
  • -XX:+PrintGCTimeStamps
  • -Xloggc:filename

回收器设置

  • -XX:+UseSerialGC: 设置串行收集器
  • -XX:+UseParallelGC: 设置并行收集器
  • -XX:+UseParalledlOldGC:设置并行年老代收集器
  • -XX:+UseConcMarkSweepGC:设置并发收集器

并行收集器设置

  • -XX:ParallelGCThreads

    指定并行 GC 线程的数量。默认情况下,当 CPU 数量小于8,ParallelGCThreads 的值等于 CPU 数量,当 CPU 数量大于 8 时,则使用公式:ParallelGCThreads = 8 + ((N - 8) * 5/8) = 3 +((5*CPU)/ 8)

  • -XX:MaxGCPauseMillis:设置并行收集最大暂停时间

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

  • -XX:+CMSIncrementalMode: 设置为增量模式,适用于单CPU情况。

生成堆内存快照

  • -XX:+HeapDumpOnOutOfMemoryError:让JVM在发生内存溢出时自动的生成堆内存快照。
  • -XX:HeapDumpPath:快照存储路径,默认保存在JVM的启动目录下名为java_pid.hprof
  • -XX:OnOutOfMemoryError: 异常发生时执行一些操作

比如:

ruby 复制代码
-XX:+HeapDumpOnOutOfMemoryError 
-XX:HeapDumpPath=/tmp/heapdump.hprof 
-XX:OnOutOfMemoryError ="sh ~/cleanup.sh"

代码缓存

  • -XX:InitialCodeCacheSize

  • -XX:ReservedCodeCacheSize

    代码缓存确实很少引起性能问题,但是一旦发生其影响可能是毁灭性的。如果代码缓存被占满,JVM会打印出一条警告消息,并切换到interpreted-only 模式:JIT编译器被停用,字节码将不再会被编译成机器码。应用程序将继续运行,但运行速度会降低一个数量级,直到有人注意到这个问题。

  • -XX:+UseCodeCacheFlushing

    当代码缓存被填满时让JVM放弃一些编译代码,避免当代码缓存被填满的时候JVM切换到interpreted-only 模式 。

参考

相关推荐
北巷!!2 分钟前
宇信科技JAVA笔试(2024-11-26日 全部AK)
java·开发语言·科技
ᝰꫝꪉꪯꫀ3614 分钟前
JavaWeb——SpringBoot原理
java·开发语言·后端·springboot
HaiFan.8 分钟前
Spring日志
java·spring boot
爬山算法10 分钟前
Tomcat(36)Tomcat的静态资源缓存
java·缓存·tomcat
TPBoreas11 分钟前
手搓一个不用中间件的分表策略
java
、十一、12 分钟前
Tomcat的工作模式是什么?
java·tomcat
killsime14 分钟前
JavaWeb开发 : tomcat+Servlet+JSP
java·servlet·tomcat·javaweb
LightOfNight24 分钟前
Redis设计与实现第14章 -- 服务器 总结(命令执行器 serverCron函数 初始化)
服务器·数据库·redis·分布式·后端·缓存·中间件
刽子手发艺33 分钟前
云服务器部署springboot项目、云服务器配置JDK、Tomcat
java·后端·部署
北漂编程小王子36 分钟前
maven <scope>import</scope>配置作用
java·maven·maven import