docker jvm调优 tomcat_JVM参数设置对tomcat性能影响初探1

本文探讨了在Docker环境下,通过调整Tomcat的JVM参数对性能的影响。实验通过Apache JMeter施加压力,测试了不同GC策略(如Serial、Parallel、CMS、G1)下Tomcat的吞吐量。结果显示,不同的JVM设置显著影响了性能,其中Parallel和Parallel Old GC表现出较高的吞吐量。文章还介绍了JVM内存区域、垃圾收集器的工作原理,并提供了一些生产环境的JVM配置示例。

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

1 tomcat性能影响实验

1.1配置环境说明:

tomcat7

一个jsp网站

测试网站吞吐量(1个指标、停顿时间,内存的使用情况,包括回收的效率...)

1.2 工具:

apache jmeter

1.3 实现原理:

通过jmeter对tomcat增加压力,不同的虚拟机参数应该会有不同的表现。

1.4 目的:

观察不同配置参数对吞吐量的影响

2 列举如下7种测试场景

2.1 测试串行回收器

(使用-XX:+UseSerialGC 参数可以指定使用新生代串行收集器和老年代串行收集器)

-XX:+PrintGCDetails -Xmx32m -Xms32m -XX:+HeapDumpOnOutOfMemoryError -XX:+UseSerialGC

-Xloggc:d:/gc.log -XX:PermSize=32m

测试结果显示的吞吐量:908|90

2.2 扩大堆内存以提升系统性能

-XX:+PrintGCDetails -Xmx512m -Xms32m -XX:+HeapDumpOnOutOfMemoryError -XX:+UseSerialGC

-Xloggc:d:/gc.log -XX:PermSize=32m

测试结果显示的吞吐量:3362|335

2.3 调整初始堆大小

-XX:+PrintGCDetails -Xmx512m -Xms128m -XX:+HeapDumpOnOutOfMemoryError

-XX:+UseSerialGC -Xloggc:d:/gc.log -XX:PermSize=32m

测试结果显示的吞吐量:4132|412

2.4 测试ParNew回收器的表现

(使用-XX:+UseParNewGC 参数设置,表示新生代使用并行收集器,老年代使用串行收集器)

-XX:+PrintGCDetails -Xmx512m -Xms128m -XX:+HeapDumpOnOutOfMemoryError

-XX:+UseParNewGC -Xloggc:d:/gc.log -XX:PermSize=32m

测试结果显示的吞吐量:4271|426

2.5 使用ParallelOldGC回收器

(使用-XX:+UseParallelGC 参数设置,表示新生代和老年代均使用并行回收收集器)

-XX:+UseParallelGC:新生代使用并行回收收集器,老年代使用串行收集器。

-XX:+UseParallelOldGC:新生代和老年代都是用并行回收收集器。

-XX:+PrintGCDetails -Xmx512m -Xms128m -XX:+HeapDumpOnOutOfMemoryError

-XX:+UseParallelGC -XX:+UseParallelOldGC -XX:ParallelGCThreads=8 -Xloggc:d:/gc.log

-XX:PermSize=32m

测试结果显示的吞吐量:4997|498

2.6 测试CMS回收器的性能

(设置参数-XX:+UseConcMarkSweepGC 可以要求新生代使用并行收集器,老年代使用 CMS)

-XX:+PrintGCDetails -Xmx512m -Xms128m -XX:+HeapDumpOnOutOfMemoryError

-XX:+UseConcMarkSweepGC -XX:ConcGCThreads=8 -Xloggc:d:/gc.log

-XX:PermSize=32m

测试结果显示的吞吐量:4223|421

2.7 测试G1回收器的性能

-XX:+PrintGCDetails -Xmx512m -Xms128m -XX:+HeapDumpOnOutOfMemoryError

-XX:+UseG1GC -XX:+UnlockExperimentalVMOptions -XX:ParallelGCThreads=8 -Xloggc:d:/gc.log

-XX:PermSize=32m -XX:MaxGCPauseMillis=200 -XX:MaxGCPauseMills=20

测试结果显示的吞吐量:3298|329

2.8 -XX:HeapDumpOnOutOfMemoryError

另一个与之相关联的参数: -XX:HeapDumpPath=/temp/ 该参数的含义是指定dump的文件目录

3.其它说明

3.1 JVM的新特性(jdk1.8)

使用Metaspace(JEP 122)代替持久代(PermGen space)。在JVM参数方面,使用-XX:MetaSpaceSize和-XX:MaxMetaspaceSize代替原来的-XX:PermSize和-XX:MaxPermSize

3.2 一张简单说明JVM垃圾回收

clipboard.png

垃圾收集器

young区

1.Serial

关注点:stw的时间 复制算法 STW

2.ParNew

关注点:stw的时间 Serial的多线程版本 复制算法 STW

参数 -XX:ParallelGCThreads 并行线程数

3.Parallel Scavenge

关注点:达到一个可控制的吞吐量(吞吐量优先) 复制算法

所谓吞吐量就是CPU运行用户代码的时间和CPU消耗的时间的比值,即吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间)。

Paralled Scavenge 收集器提供了两个参数用于精确控制吞吐量。分别是控制最大垃圾收集停顿时间的-XX:MaxGCPauseMillis ,以及直接设置吞吐量大小的-XX:GCTimeRatio 参数。

参数

-XX:MaxGCPauseMillis

-XX:GCTimeRatio

-XX:+UseAdaptiveSizePolicy 自适应调节策略

old区

1.Serial Old

Serial的老年代版本

JDK1.5之前可搭配Parallel Scavenge使用

在CMS发生Concurrent mode failure时使用

Mark-Compact

2.Parallel Old

Parallel Scavenge的老年代版本

JDK1.6出现 搭配Parallel Scavenge使用

Mark-Compact

3.CMS

-XX:+UseConcMarkSweepGC

Mark-Sweep

过程:初始标记 并发标记 重新标记 并发清除

初始标记和重新标记会STW

耗时最长是并发标记和并发清除

默认回收线程数:CMS默认启动的回收线程数目是 (ParallelGCThreads + 3)/4),可以通过-XX:ParallelCMSThreads=20来设定

优点:并发低停顿

缺点:

1、对CPU资源非常敏感

占用部分线程(CPU资源)导致应用程序变慢,吞吐量降低

默认线程数=(CPU数量+3)/4

2、无法处理浮动垃圾,可能出现Concurrent mode failure而导致另一次fullGC的产生

参数-XX:CMSInitiatingOccupancyFraction默认68% CMS触发百分比,CMS执行期间,预留空间无法满足,就会出现Concurrent mode failure失败,启动后备SerialOld的方案,停顿时间更长了。(所以CMSInitiatingOccupancyFraction不能设置的过大)

3、内存碎片

参数-XX:+UseCMSCompactAtFullCollection(停顿时间加长) 默认开启

-XX:CMSFullGCsBeforeCompaction(执行多少次不进行碎片整理的FullGC后进行一次带压缩的)

其他参数

初始标记的并行化-XX:+CMSParallelInitialMarkEnabled

为了减少第二次暂停的时间,开启并行remark: -XX:+CMSParallelRemarkEnabled,如果remark还是过长的话,可以开启-XX:+CMSScavengeBeforeRemark(在CMS GC前启动一次ygc,目的在于减少old gen对ygc gen的引用,降低remark时的开销-----一般CMS的GC耗时 80%都在remark阶段)

为了避免Perm区满引起的full gc,建议开启CMS回收Perm区选项:

+CMSPermGenSweepingEnabled -XX:+CMSClassUnloadingEnabled

-XX:+UseConcMarkSweepGC:设置年老代为并发收集。测试中配置这个以后,-XX:NewRatio=4的配置失效了,原因不明。所以,此时年轻代大小最好用-Xmn设置。

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

G1收集器

收集器组合开关选项

-XX:+UseSerialGC Serial+SerialOld

-XX:+UseParNewGC ParNew+SerialOld

-XX:+UseParallelGC ParallelScavenge+SerialOld

-XX:+UseConcMarkSweepGC ParNew+CMS+SerialOld FullGC算法:单线程的Mark Sweep Compact(MSC)

-XX:+UseParallelOldGC ParallelScavenge+Parallel Old FullGC算法:PS MarkSweep

JVM参数

垃圾回收参数

-Xnoclassgc 是否对类进行回收

-verbose:class -XX:+TraceClassUnloading 查看类加载和卸载信息

-XX:SurvivorRatio Eden和其中一个survivor的比值

-XX:PretenureSizeThreshold 大对象进入老年代的阈值,Serial和ParNew生效

-XX:MaxTenuringThreshold 晋升老年代的对象年龄,默认15, CMS默认是4

-XX:HandlePromotionFailure 老年代担保

-XX:+UseAdaptiveSizePolicy动态调整Java堆中各个区域大小和进入老年代年龄

-XX:ParallelGCThreads 并行回收的线程数

-XX:MaxGCPauseMillis Parallel Scavenge参数,设置GC的最大停顿时间

-XX:GCTimeRatio Parallel Scavenge参数,GC时间占总时间的比率,默认99%,即1%的GC时间

-XX:CMSInitiatingOccupancyFraction,old区触发cms阈值,默认68%

-XX:+UseCMSCompactAtFullCollection(CMS完成后是否进行一次碎片整理,停顿时间加长)

-XX:CMSFullGCsBeforeCompaction(执行多少次不进行碎片整理的FullGC后进行一次带压缩的)

-XX:+ScavengeBeforeFullGC,在fullgc前触发一次minorGC

垃圾回收统计信息

-XX:+PrintGC 输出GC日志

-verbose:gc等同于上面那个

-XX:+PrintGCDetails 输出GC的详细日志

堆大小设置

-Xmx:最大堆大小

-Xms:初始堆大小(最小内存值)

-Xmn:年轻代大小

-XX:NewSize和-XX:MaxNewSize 新生代大小

-XX:SurvivorRatio:3 意思是年轻代中Eden区与两个Survivor区的比值。注意Survivor区有两个。如:3,表示Eden:Survivor=3:2,一个Survivor区占整个年轻代的1/5

-XX:NewRatio=4:设置年轻代(包括Eden和两个Survivor区)与年老代的比值(除去持久代)。设置为4,则年轻代与年老代所占比值为1:4,年轻代占整个堆栈的1/5

-Xss栈容量 默认256k

-XX:PermSize永久代初始值

-XX:MaxPermSize 永久代最大值

生产环境参数配置(CMS-GC)

Java < 8

-server

-Xms[g|m|k] -Xmx[g|m|k]

-XX:PermSize=[g|m|k] -XX:MaxPermSize=[g|m|k]

-Xmn[g|m|k]

-XX:+DisableExplicitGC

-XX:SurvivorRatio=

-XX:+UseConcMarkSweepGC

-XX:+CMSParallelRemarkEnabled

-XX:+CMSScavengeBeforeRemark

-XX:+UseCMSInitiatingOccupancyOnly

-XX:CMSInitiatingOccupancyFraction=

-XX:+PrintGCDateStamps -verbose:gc -XX:+PrintGCDetails -Xloggc:""

-XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M

-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=`date`.hprof

-Dsun.net.inetaddr.ttl=

-Djava.rmi.server.hostname=

-Dcom.sun.management.jmxremote.port=

-Dcom.sun.management.jmxremote.authenticate=false

-Dcom.sun.management.jmxremote.ssl=false

Java >= 8

-server

-Xms[g|m|k] -Xmx[g|m|k]

-XX:MaxMetaspaceSize=[g|m|k]

-Xmn[g|m|k]

-XX:+DisableExplicitGC

-XX:SurvivorRatio=

-XX:+UseConcMarkSweepGC

-XX:+CMSParallelRemarkEnabled

-XX:+CMSScavengeBeforeRemark

-XX:+UseCMSInitiatingOccupancyOnly

-XX:CMSInitiatingOccupancyFraction=

-XX:+PrintGCDateStamps -verbose:gc -XX:+PrintGCDetails -Xloggc:""

-XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M

-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=`date`.hprof

-Dsun.net.inetaddr.ttl=

-Djava.rmi.server.hostname=

-Dcom.sun.management.jmxremote.port=

-Dcom.sun.management.jmxremote.authenticate=false

-Dcom.sun.management.jmxremote.ssl=false

理解GC日志

DefNew:Serial收集器新生代名称 - Tenured - Perm

ParNew:ParNew收集器新生代名称 -

PSYoungGen:Parallel Scavenge收集器新生代名称

JVM调优

GC的时间足够的小

GC的次数足够的少

发生Full GC的周期足够的长

前两个目前是相悖的,要想GC时间小必须要一个更小的堆,要保证GC次数足够少,必须保证一个更大的堆,我们只能取其平衡。

(1)针对JVM堆的设置,一般可以通过-Xms -Xmx限定其最小、最大值,为了防止垃圾收集器在最小、最大之间收缩堆而产生额外的时间,我们通常把最大、最小设置为相同的值

(2)年轻代和年老代将根据默认的比例(1:2)分配堆内存,可以通过调整二者之间的比率NewRadio来调整二者之间的大小,也可以针对回收代,比如年轻代,通过 -XX:newSize -XX:MaxNewSize来设置其绝对大小。同样,为了防止年轻代的堆收缩,我们通常会把-XX:newSize -XX:MaxNewSize设置为同样大小。-XX:PermSize,-XX:MaxPermSize设置为一样防止老年代收缩。

-XX:NewRatio=4:设置年轻代(包括Eden和两个Survivor区)与年老代的比值(除去持久代)。设置为4,则年轻代与年老代所占比值为1:4,年轻代占整个堆栈的1/5

-XX:MaxTenuringThreshold=0:设置垃圾最大年龄。如果设置为0的话,则年轻代对象不经过Survivor区,直接进入年老代。对于年老代比较多的应用,可以提高效率。如果将此值设置为一个较大值,则年轻代对象会在Survivor区进行多次复制,这样可以增加对象再年轻代的存活时间,增加在年轻代即被回收的概论。

(3)年轻代和年老代设置多大才算合理?这个我问题毫无疑问是没有答案的,否则也就不会有调优。我们观察一下二者大小变化有哪些影响

年轻代老年代设置:整个JVM内存大小=年轻代大小 + 年老代大小 + 持久代大小。持久代一般固定大小为64m,所以增大年轻代后,将会减小年老代大小。此值对系统性能影响较大,Sun官方推荐年轻代配置为整个堆的3/8。

更大的年轻代必然导致更小的年老代,大的年轻代会延长普通GC的周期,但会增加每次GC的时间;小的年老代会导致更频繁的Full GC

更小的年轻代必然导致更大年老代,小的年轻代会导致普通GC很频繁,但每次的GC时间会更短;大的年老代会减少Full GC的频率

如何选择应该依赖应用程序对象生命周期的分布情况:如果应用存在大量的临时对象,应该选择更大的年轻代;如果存在相对较多的持久对象,年老代应该适当增大。但很多应用都没有这样明显的特性,在抉择时应该根据以下两点:(A)本着Full GC尽量少的原则,让年老代尽量缓存常用对象,JVM的默认比例1:2也是这个道理 (B)通过观察应用一段时间,看其他在峰值时年老代会占多少内存,在不影响Full GC的前提下,根据实际情况加大年轻代,比如可以把比例控制在1:1。但应该给年老代至少预留1/3的增长空间

(4)在配置较好的机器上(比如多核、大内存),可以为年老代选择并行收集算法: -XX:+UseParallelOldGC ,默认为Serial收集

(5)线程堆栈的设置:每个线程默认会开启1M的堆栈,用于存放栈帧、调用参数、局部变量等,对大多数应用而言这个默认值太了,一般256K就足用。理论上,在内存不变的情况下,减少每个线程的堆栈,可以产生更多的线程,但这实际上还受限于操作系统。 -Xss256k:设置每个线程的堆栈大小。JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K。更具应用的线程所需内存大小进行调整。在相同物理内存下,减小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右。

(6)可以通过下面的参数打Heap Dump信息

-XX:HeapDumpPath

-XX:+PrintGCDetails

-XX:+PrintGCTimeStamps

-Xloggc:/usr/aaa/dump/heap_trace.txt

通过下面参数可以控制OutOfMemoryError时打印堆的信息

-XX:+HeapDumpOnOutOfMemoryError

注:通过分析dump文件可以发现,每个1小时都会发生一次Full GC,经过多方求证,只要在JVM中开启了JMX服务,JMX将会1小时执行一次Full GC以清除引用.

性能分析工具

jps

-m 主类的参数

-l 主类的全名,如果执行的是jar包,输出jar路径

-v 虚拟机参数

jstat

监视虚拟机运行状态信息,包括类装载、GC、运行期编译(JIT)

用于输出java程序内存使用情况,包括新生代、老年代、元数据区容量、垃圾回收情况

jstat -gcutil 52670 2000 5 进程号 2s输出一次一共5次

S0:幸存1区当前使用比例

S1:幸存2区当前使用比例

E:伊甸园区使用比例

O:老年代使用比例

M:元数据区使用比例

CCS:压缩使用比例

YGC:年轻代垃圾回收次数

YGCT:年轻代垃圾回收消耗时间

FGC:老年代垃圾回收次数

FGCT:老年代垃圾回收消耗时间

GCT:垃圾回收消耗总时间

jmap

jmap:用于生成堆转储快照。一般称为dump或heapdump文件。

jmap -histo 3618

上述命令打印出进程ID为3618的内存情况,包括有哪些对象,对象的数量。但我们常用的方式是将指定进程的内存heap输出到外 部文件,再由专门的heap分析工具进行分析,例如mat(Memory Analysis Tool),所以我们常用的命令是:

jmap -dump:live,format=b,file=heap.hprof 3618

-F 强制生成dump快照

jstack

jstack:用户输出虚拟机当前时刻的线程快照,常用于定位因为某些线程问题造成的故障或性能问题。一般称为threaddump文件。

参数

-F当正常输出没有响应的时候强制打印栈信息,一般情况不需要使用

-l长列表. 打印关于锁的附加信息,一般情况不需要使用

-m 如果调用本地方法的话,可打印c/c++的堆栈

jinfo

查看和修改虚拟机参数

可视化工具

JConsole Java监视与管理控制台

VisualVM 多合一故障处理工具

Java Class文件类型前缀

Element Type Encoding

boolean Z

byte B

char C

double D

float F

int I

long J

short S

class or interface Lclassname;

[L代表了相应类型数组嵌套的层数

内存泄漏及解决方法

1.系统崩溃前的一些现象:

每次垃圾回收的时间越来越长,由之前的10ms延长到50ms左右,FullGC的时间也有之前的0.5s延长到4、5s

FullGC的次数越来越多,最频繁时隔不到1分钟就进行一次FullGC

年老代的内存越来越大并且每次FullGC后年老代没有内存被释放

之后系统会无法响应新的请求,逐渐到达OutOfMemoryError的临界值。

2.生成堆的dump文件

通过JMX的MBean生成当前的Heap信息,大小为一个3G(整个堆的大小)的hprof文件,如果没有启动JMX可以通过Java的jmap命令来生成该文件。

3.分析dump文件

下面要考虑的是如何打开这个3G的堆信息文件,显然一般的Window系统没有这么大的内存,必须借助高配置的Linux。当然我们可以借助X-Window把Linux上的图形导入到Window。我们考虑用下面几种工具打开该文件:

1.Visual VM

2.IBM HeapAnalyzer

3.JDK 自带的Hprof工具

使用这些工具时为了确保加载速度,建议设置最大内存为6G。使用后发现,这些工具都无法直观地观察到内存泄漏,Visual VM虽能观察到对象大小,但看不到调用堆栈;HeapAnalyzer虽然能看到调用堆栈,却无法正确打开一个3G的文件。因此,我们又选用了Eclipse专门的静态内存分析工具:Mat。

4.分析内存泄漏

通过Mat我们能清楚地看到,哪些对象被怀疑为内存泄漏,哪些对象占的空间最大及对象的调用关系。针对本案,在ThreadLocal中有很多的JbpmContext实例,经过调查是JBPM的Context没有关闭所致。

另,通过Mat或JMX我们还可以分析线程状态,可以观察到线程被阻塞在哪个对象上,从而判断系统的瓶颈。

5.回归问题

Q:为什么崩溃前垃圾回收的时间越来越长?

A:根据内存模型和垃圾回收算法,垃圾回收分两部分:内存标记、清除(复制),标记部分只要内存大小固定,时间是不变的,变的是复制部分,因为每次垃圾回收都有一些回收不掉的内存,所以增加了复制量,导致时间延长。所以,垃圾回收的时间也可以作为判断内存泄漏的依据

Q:为什么Full GC的次数越来越多?

A:因此内存的积累,逐渐耗尽了年老代的内存,导致新对象分配没有更多的空间,从而导致频繁的垃圾回收

Q:为什么年老代占用的内存越来越大?

A:因为年轻代的内存无法被回收,越来越多地被Copy到年老代

调优方法

一切都是为了这一步,调优,在调优之前,我们需要记住下面的原则:

1、多数的Java应用不需要在服务器上进行GC优化;

2、多数导致GC问题的Java应用,都不是因为我们参数设置错误,而是代码问题;

3、在应用上线之前,先考虑将机器的JVM参数设置到最优(最适合)

4、减少创建对象的数量;

5、减少使用全局变量和大对象;

6、GC优化是到最后不得已才采用的手段;

7、在实际使用中,分析GC情况优化代码比优化GC参数要多得多;

GC优化的目的有两个

1、将转移到老年代的对象数量降低到最小;

2、减少full GC的执行时间;

为了达到上面的目的,一般地,你需要做的事情有:

1、减少使用全局变量和大对象;

2、调整新生代的大小到最合适;

3、设置老年代的大小为最合适;

4、选择合适的GC收集器

<think>我们正在讨论JVM参数的设置位置和配置方法。根据引用内容,JVM参数主要用于配置内存大小、垃圾回收策略等。这些参数可以在不同环境中设置,具体取决于应用程序的启动方式。 常见的设置位置包括: 1. 命令行启动:直接在java命令后添加参数,如:java -Xms512m -Xmx1024m -jar application.jar 2. 在IDE(如IntelliJ IDEA、Eclipse)中运行配置里设置VM options 3. 对于Tomcat等应用服务器,可以在启动脚本(如catalina.sh或catalina.bat)中设置环境变量JAVA_OPTS或CATALINA_OPTS 4. 对于Spring Boot项目,可以通过application.properties配置,但注意Spring Boot 2.x后部分参数需通过命令行或环境变量设置 5. 在Docker容器中,可以通过环境变量JAVA_OPTS或直接在启动命令中设置 引用[2]和[3]展示了一些具体的参数设置示例,例如: -Xms3G -Xmx3G 设置堆内存初始大小和最大大小 -XX:PermSize=128m -XX:MaxPermSize=128m 设置永久代大小(注意:Java 8及以后已移除永久代,取而代之的是元空间,参数为-XX:MetaspaceSize和-XX:MaxMetaspaceSize) -XX:+UseParallelOldGC 指定垃圾回收器 配置方法详细说明: 1. 命令行方式:在启动Java应用程序时,在java命令后添加参数。 2. 应用服务器(以Tomcat为例): - 在Linux系统中,编辑catalina.sh文件,在文件开头添加: JAVA_OPTS="$JAVA_OPTS -Xms512m -Xmx1024m" - 在Windows系统中,编辑catalina.bat文件,添加: set JAVA_OPTS=%JAVA_OPTS% -Xms512m -Xmx1024m 3. IDE配置(以IntelliJ IDEA为例): - 打开运行配置(Run/Debug Configurations),在VM options框中输入参数,例如:-Xmx2048m -XX:+UseG1GC 4. Spring Boot项目: - 可以通过命令行:java -jar -Xmx1024m app.jar - 或者在application.properties中配置(部分参数):例如,设置垃圾回收日志:-Dlogging.level.org.springframework=INFO(但注意,JVM内存参数不能在application.properties中设置,因为此时JVM已经启动) 5. 使用Docker时,可以在Dockerfile中通过ENV设置环境变量,或者在docker run命令中设置环境变量: docker run -e "JAVA_OPTS=-Xmx1024m" my-java-app 注意:永久代(PermGen)在Java 8中被移除,取而代之的是元空间(Metaspace),因此对于Java 8及以上版本,应使用: -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=256m 另外,引用[3]中的参数示例还包含了其他有用的参数,例如: -XX:+HeapDumpOnOutOfMemoryError 在内存溢出时生成堆转储文件 -XX:HeapDumpPath 指定堆转储文件的路径 -XX:+PrintGCDetails 打印GC详细信息 -Xloggc 指定GC日志文件 在配置时,需要根据应用程序的实际需求和运行环境来整参数值。例如,堆内存大小(-Xms和-Xmx)通常设置为相同值以避免运行时动态整带来的性能波动,但具体数值取决于可用物理内存和应用程序的内存需求。 最后,在设置完参数后,需要通过监控工具(如jstat、VisualVM等)来观察JVM的运行状态,验证效果,并进一步整。</think>### JVM参数的设置位置及配置方法 JVM参数主要通过以下四种方式配置,配置位置取决于应用部署环境: --- #### 一、命令行启动参数(通用方式) **适用场景**:本地试、命令行启动的Java应用 **配置方法**:在 `java` 命令后直接添加参数 ```bash java -Xms3G -Xmx3G -XX:+UseG1GC -jar your_app.jar ``` **关键参数示例**: - `-Xms3G`:初始堆内存(如引用[3]) - `-Xmx3G`:最大堆内存(如引用[2][3]) - `-XX:+UseG1GC`:启用G1垃圾回收器 - `-Xloggc:/path/gc.log`:GC日志路径(如引用[3]) > ✅ **点**:灵活即时,无需修改文件 > ⚠️ **注意**:参数间用空格分隔,大小写敏感 --- #### 二、应用服务器配置文件 **1. Tomcat** - **Linux/Mac**:编辑 `catalina.sh` ```bash JAVA_OPTS="$JAVA_OPTS -Xms2G -Xmx2G -XX:MaxMetaspaceSize=512m" ``` - **Windows**:编辑 `catalina.bat` ```bat set "JAVA_OPTS=%JAVA_OPTS% -Xms2G -Xmx2G" ``` **2. WebLogic/WebSphere** - 在管理控制台的 **JVM参数配置页** 直接填写(如图形化界面) --- #### 三、IDE开发环境配置 **IntelliJ IDEA**: 1. `Run` → `Edit Configurations` 2. 在 `VM options` 输入参数: ```bash -Xms512m -Xmx1024m -XX:+HeapDumpOnOutOfMemoryError ``` ![IDEA配置示例](https://example.com/jvm-options-idea.png) **Eclipse**: `Run Configurations` → `Arguments` → `VM arguments` --- #### 四、容器化部署(Docker/K8s) **1. Dockerfile**:通过 `JAVA_OPTS` 环境变量 ```dockerfile ENV JAVA_OPTS="-Xms1G -Xmx1G -XX:+UseZGC" CMD java ${JAVA_OPTS} -jar app.jar ``` **2. Kubernetes部署文件**: ```yaml containers: - name: java-app env: - name: JAVA_OPTS value: "-Xmx2048m -XX:MaxRAMPercentage=75%" ``` --- ### 配置注意事项 1. **参数先级**:命令行参数 > 环境变量 > 配置文件 2. **堆内存设置**: - `-Xms` 和 `-Xmx` 通常设为相同值(避免动态整开销) - 推荐不超过物理内存的50%(如引用[2]示例) 3. **元空间(Java 8+)**: ```bash -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=256m # 替代PermGen参数 ``` 4. **GC日志**:生产环境必须启用(如引用[3]) ```bash -XX:+PrintGCDetails -Xloggc:/logs/gc.log ``` --- ### 参数验证方法 1. **检查运行时参数**: ```bash jcmd <pid> VM.flags ``` 2. **监控工具**: - `jstat -gc <pid>`:实时GC统计 - VisualVM/JConsole:图形化监控堆内存使用 > ⚠️ **警告**:避免盲目复制参数,需根据实际负载测试整。例如: > - 高并发系统:需降低`-XX:NewRatio`(如设为2-3) > - 低延迟场景:先选ZGC或Shenandoah[^1]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值