JVM原理及优化_调优原则与工具

本文详细介绍了JVM参数配置、GC收集器设置及调优策略,涵盖JVM内存参数、不同部署环境下JVM参数设置方法,并提供了一套完整的调优流程与实践建议。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

JVM参数配置

JVM内存参数简述
#常用的设置
-Xms:初始堆大小,JVM 启动的时候,给定堆空间大小。 

-Xmx:最大堆大小,JVM 运行过程中,如果初始堆空间不足的时候,最大可以扩展到多少。 

-Xmn:设置堆中年轻代大小。整个堆大小=年轻代大小+年老代大小+持久代大小。 

-XX:NewSize=n 设置年轻代初始化大小大小 

-XX:MaxNewSize=n 设置年轻代最大值

-XX:NewRatio=n 设置年轻代和年老代的比值。如: -XX:NewRatio=3,表示年轻代与年老代比值为 13,年轻代占整个年轻代+年老代和的 1/4 

-XX:SurvivorRatio=n 年轻代中 Eden 区与两个 Survivor 区的比值。注意 Survivor 区有两个。8表示两个Survivor :eden=2:8 ,即一个Survivor占年轻代的1/10,默认就为8

-Xss:设置每个线程的堆栈大小。JDK5后每个线程 Java 栈大小为 1M,以前每个线程堆栈大小为 256K。

-XX:ThreadStackSize=n 线程堆栈大小

-XX:PermSize=n 设置持久代初始值	

-XX:MaxPermSize=n 设置持久代大小
 
-XX:MaxTenuringThreshold=n 设置年轻带垃圾对象最大年龄。如果设置为 0 的话,则年轻代对象不经过 Survivor 区,直接进入年老代。

#下面是一些不常用的

-XX:LargePageSizeInBytes=n 设置堆内存的内存页大小

-XX:+UseFastAccessorMethods 优化原始类型的getter方法性能

-XX:+DisableExplicitGC 禁止在运行期显式地调用System.gc(),默认启用	

-XX:+AggressiveOpts 是否启用JVM开发团队最新的调优成果。例如编译优化,偏向锁,并行年老代收集等,jdk6纸之后默认启动

-XX:+UseBiasedLocking 是否启用偏向锁,JDK6默认启用	

-Xnoclassgc 是否禁用垃圾回收

-XX:+UseThreadPriorities 使用本地线程的优先级,默认启用	

等等等......
JVM的GC收集器设置
-XX:+UseSerialGC:设置串行收集器,年轻带收集器 

 -XX:+UseParNewGC:设置年轻代为并行收集。可与 CMS 收集同时使用。JDK5.0 以上,JVM 会根据系统配置自行设置,所以无需再设置此值。

-XX:+UseParallelGC:设置并行收集器,目标是目标是达到可控制的吞吐量

-XX:+UseParallelOldGC:设置并行年老代收集器,JDK6.0 支持对年老代并行收集。 

-XX:+UseConcMarkSweepGC:设置年老代并发收集器

-XX:+UseG1GC:设置 G1 收集器,JDK1.9默认垃圾收集器
IDEA在哪里设置JVM参数

全局的配置

  1. 找到IDEA安装目录中的bin目录
  2. 找到idea.exe.vmoptions文件
  3. 打开该文件编辑并保存。
war(Tomcat)包在哪里设置JVM参数

war肯定是部署在Tomcat上的,那就是修改Tomcat的JVM参数

在Windows下就是在文件/bin/catalina.bat,
增加如下设置:JAVA_OPTS(JAVA_OPTS,就是用来设置 JVM 相关运行参数的变量)

set "JAVA_OPTS=-Xms512M -Xmx1024M ...等等等 JVM参数"

Linux要在tomcat 的bin 下的catalina.sh 文件里添加

注意:位置要在cygwin=false前
JAVA_OPTS="-Xms512M -Xmx1024M ...等等等 JVM参数"

Jar包在哪里设置JVM参数

Jar包简单,一般都是SpringBoot项目打成Jar包来运行

#运行时java -jar是直接插入JVM命令就好了
java -Xms1024m -Xmx1024m ...等等等 JVM参数 -jar springboot_app.jar & 

调优场景

  • 目的

GC的时间够小
GC的次数够少
发生Full GC的周期足够的长,时间合理,最好是不发生。

  • 调优的原则和步骤
  1. 大多数的java应用不需要GC调优
  1. 大部分需要GC调优的的,不是参数问题,是代码问题
  2. 在实际使用中,分析GC情况优化代码比优化GC参数要多得多;
  3. GC调优是最后的手段
    GC调优的最重要的三个选项:
    第一位:选择合适的GC回收器
    第二位:选择合适的堆大小
    第三位:选择年轻代在堆中的比重

步骤

1.监控GC的状态

使用各种JVM工具,查看当前日志,分析当前JVM参数设置,并且分析当前堆内存快照和gc日志,根据实际的各区域内存划分和GC执行时间,觉得是否进行优化;

2.分析结果,判断是否需要优化

如果各项参数设置合理,系统没有超时日志出现,GC频率不高,GC耗时不高,那么没有必要进行GC优化;如果GC时间超过1-3秒,或者频繁GC,则必须优化;
注:如果满足下面的指标,则一般不需要进行GC:
Minor GC执行时间不到50ms;
Minor GC执行不频繁,约10秒一次;
Full GC执行时间不到1s;
Full GC执行频率不算频繁,不低于10分钟1次;

3.调整GC类型和内存分配

如果内存分配过大或过小,或者采用的GC收集器比较慢,则应该优先调整这些参数,并且先找1台或几台机器进行beta,然后比较优化过的机器和没有优化的机器的性能对比,并有针对性的做出最后选择;

4.不断的分析和调整

通过不断的试验和试错,分析并找到最合适的参数

5.全面应用参数

如果找到了最合适的参数,则将这些参数应用到所有服务器,并进行后续跟踪。

推荐策略

  • 年轻代大小选择
  1. 响应时间优先的应用:尽可能设大,直到接近系统的最低响应时间限制(根据实际情况选择).在此种情况下,年轻代收集发生的频率也是最小的.同时,减少到达年老代的对象.
  1. 吞吐量优先的应用:尽可能的设置大,可能到达Gbit的程度.因为对响应时间没有要求,垃圾收集可以并行进行,一般适合8CPU以上的应用.
  2. 避免设置过小.当新生代设置过小时会导致:1.YGC次数更加频繁 2.可能导致YGC对象直接进入旧生代,如果此时旧生代满了,会触发FGC.
  • 年老代大小选择
  1. 响应时间优先的应用:年老代使用并发收集器,所以其大小需要小心设置,一般要考虑并发会话率和会话持续时间等一些参数.如果堆设置小了,可以会造成内存碎片,高回收频率以及应用暂停而使用传统的标记清除方式;如果堆大了,则需要较长的收集时间.最优化的方案,一般需要参考以下数据获得:
  1. 并发垃圾收集信息、持久代并发收集次数、传统GC信息、花在年轻代和年老代回收上的时间比例。
  2. 吞吐量优先的应用一般吞吐量优先的应用都有一个很大的年轻代和一个较小的年老代.原因是,这样可以尽可能回收掉大部分短期对象,减少中期的对象,而年老代尽存放长期存活对象
调优总结
  1. 在实际工作中,我们可以直接将初始的堆大小与最大堆大小相等,
    这样的好处是可以减少程序运行时垃圾回收次数,从而提高效率。
  2. 初始堆值和最大堆内存内存越大,吞吐量就越高,
    但是也要根据自己电脑(服务器)的实际内存来比较。
  3. 最好使用并行收集器,因为并行收集器速度比串行吞吐量高,速度快。
    当然,服务器一定要是多线程的
  4. 设置堆内存新生代的比例和老年代的比例最好为1:2或者1:3。
    默认的就是1:2
  5. 减少GC对老年代的回收。设置生代带垃圾对象最大年龄,进量不要有大量连续内存空间的java对象,因为会直接到老年代,内存不够就会执行GC

注释:其实最主要的还是服务器要好,你硬件都跟不上,软件再好都没用
注释:老年代GC很慢,新生代没啥事
注释:默认的JVM堆大小好像是电脑实际内存的四分之一左右,

public class Test {
    public static void main(String[] args) {
        System.out.print("最大内存");
        System.out.println(Runtime.getRuntime().maxMemory() / 1024.0 / 1024 + "M");
    }
}

可视化工具

JVM可视化工具
  1. 为什么要可视化工具
    开发大型 Java 应用程序的过程中难免遇到内存泄露、性能瓶颈等问题,比如文件、网络、数据库的连接未释放,未优化的算法等。随着应用程序的持续运行,可能会造成整个系统运行效率下降,严重的则会造成系统崩溃。为了找出程序中隐藏的这些问题,在项目开发后期往往会使用性能分析工具来对应用程序的性能进行分析和优化。
visualVm

VisualVM 是一款免费的,集成了多个 JDK 命令行工具的可视化工具,它能为您提供强大的分析能力,对 Java 应用程序做性能分析和调优。这些功能包括生成和分析海量数据、跟踪内存泄漏、监控垃圾回收器、执行内存和 CPU 分析,同时,它能自动选择更快更轻量级的技术尽量减少性能分析对应用程序造成的影响,提高性能分析的精度。

他作为Oracle JDK 的一部分,位于 JDK 根目录的 bin 文件夹下。VisualVM 自身要在 JDK6 以上的版本上运行,但是它能够监控 JDK1.4 以上版本的应用程序

打开visualVm

位于 JDK 根目录的 bin 文件夹下的jvisualvm.exe

本地测试项目JVM运行状态

我这本地有了好几个进程,这是我IDea工具的

我运行一个SpringBoot项目

此时就开始监控了

jconsole

从Java 5开始 引入了 JConsole。JConsole 是一个内置 Java 性能分析器,可以从命令行或在 GUI shell 中运行。您可以轻松地使用 JConsole(或者,它更高端的 “近亲” VisualVM )来监控 Java 应用程序性能和跟踪 Java 中的代码。

点击jdk/bin 目录下面的jconsole.exe 即可启动,然后会自动自动搜索本机运行的所有虚拟机进程。选择其中一个进程可开始进行监控

远程连接项目也很简单,和 visualVm基本一致,可以自己研究一下
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IT二叔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值