jvm 常用配置参数


jvm配置参数分为3大类:
1、堆分配参数:分配堆内存
2、栈分配参数:分配栈内存
3、跟踪参数:跟踪、监控JVM状态,用于程序员JVM调优及故障排查

# java -jar配置参数示例

# 堆最小200M,堆最大200M,栈内存512K,打印GC详细信息
java -Xms200m -Xmx200m -Xss512K -XX:+PrintGCDetails -jar demo-0.0.1-SNAPSHOT.jar 

1、常用堆分配参数

堆参数作用
-Xms最小堆
-Xmx最大堆
-Xmn新生代内存
-XX:NewRatio新生代和老年代比值
-XX:SurvivorRatio新生代中Survivor区与Eden区的比值

1、最大堆:-Xmx,java程序最大能使用多少内存大小,如果超过这个大小,那么java程序会报:out of memory(OOM错误)
2、最小堆:-Xms
3、指定新生代的内存:-Xmn
4、总的堆:目前程序已经配置到的内存大小。一般而言程序一启动,会按照-Xms5m先分配5M的空间,这时总的堆大小就是5M。
5、空闲堆:程序已经分配的内存大小减去已经使用的内存大小
6、内存分配比例
新生代(eden+from+to)和老年代(不包含永久区)的比值:-XX:NewRatio。
默认是 young : old = 1 : 2

!!!
注意是 1:2 ,不是 1/2

Survivor区与Eden区的比值:-XX:SurvivorRatio。
默认是 Eden : from : to = 8 : 1 : 1

这2个比值的计算规则如下:

若-XX:NewRatio=4,则表示 新生代 : 老年代 = 1 : 4 ,那么总内存是1000M的话,新生代就是200M,老年代是800M。200 : 800 = 1:4。

若-XX:SurvivorRatio=3,则表示新生代中的比例为 Survivor-from区 : Survivor-to区 : Eden区=1 : 1 : 3,那么Survivor区(from+to)= 40+40=80M,Eden区=120M。

我这里启动了一个jvm进程可以供大家验证。总内存为1000M,并配置-XX:NewRatio=4 和 -XX:SurvivorRatio=3,大家可以自己计算下。
(S0C代表年轻代中的S0区域内存大小;S1C代表年轻代中S1区域内存大小;EC代表年轻代中Eden区域内存大小;OC代表老年代内存大小;以上加起来就是总内存,单位是KB)
S0C代表年轻代中的S0区域内存大小;S1C代表年轻代中S1区域内存大小;EC代表年轻代中Eden区域内存大小;OC代表老年代内存大小;(KB)

7、官方推荐:
新生代占堆的3:8
幸存代占新生代的1:10
8、发生OOM异常时把堆栈信息打印到外部文件
第1个:-XX:+HeapDumpOnOutOfMemoryError
第2个:-XX:+HeapDumpPath

9、将堆的最小值-Xms 参数与最大值-Xmx 参数设置为一样即可避免堆自动扩展。因为JVM初始分配的内存由-Xms指定,默认是物理内存的1/64;JVM最大分配的内存由-Xmx指 定,默认是物理内存的1/4。默认空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制;空余堆内存大于70%时,JVM会减少堆直到 -Xms的最小限制。因此服务器一般设置-Xms、-Xmx相等以避免在每次GC 后调整堆的大小。对象的堆内存由称为垃圾回收器的自动内存管理系统回收。

2、常用栈分配参数

栈参数作用
-Xss栈大小

1、栈大小参数为-Xss
栈大小通常只有几百k,决定于函数调用的深度。每个线程都有自己独立的栈空间(私有栈空间,不共享)。如果函数调用太深,超过了栈的大小,则会抛出java.lang.StackOverflowError。遇到这种错误,通常情况下,不是去调整-Xss参数,而是应该去检查是否是函数调用太深导致的,是否使用了递归,能不能保证递归出口等。

3、常用跟踪监控参数

跟踪监控参数作用
-XX:+PrintGC打印gc简要信息
-verbose:gc打印gc简要信息
-XX:+PrintGCDetails打印gc详细信息及堆使用详细信息
-Xloggc:log/gc.log将gc日志记录到外部文件中去

1、打印gc简要信息
第一个:-XX:+PrintGC
第二个:-verbose:gc
这2个参数效果一样,都是在发生gc时,打印gc简要信息的。以这个查看结果为例:

1: [GC (Allocation Failure) 32686K->1648K(123904K), 0.0007230 secs] 
2: [GC (Allocation Failure) 34034K->1600K(123904K), 0.0009652 secs]

解释如下:
解释1:总共发生了2次gc,因为打印出的信息标记出了1与2
解释2:以第1次gc为例,32686K表示回收前,对象占用的空间。1648K表示回收后,对象占用的空间。123904K表示还有多少空间可用。0.0007230 secs表示这次垃圾回收花费的时间。

2、打印gc详细信息及堆使用详细信息:-XX:+PrintGCDetails
解释1:堆分为新生代、老年代、元空间。
解释2:新生代中又分为伊甸区(eden)和幸存区(from和to)。
解释3:细心的同学可能会发现一种类似于这样的情况:
eden+from+to=65536K+5120K+5120K=75776 并不等于总大小70656K,这是为什么呢?这是因为新生代的垃圾回收算法是采用复制算法,简单的说,就是在from和to之间来回复制(复制过程中再把不可达的对象回收掉),所以必须保证其中一个区是空的,这样才能有预留空间存放复制过来的数据,所以新生代的总大小其实等于eden+from或eden+to=65536K+5120K=70656k。

3、将gc日志记录到外部文件中去:-Xloggc:log/gc.log(参数中gc.log就是外部文件的名称)
当java程序出现OOM异常时,总是想查看当时gc的情况,那么使用这个参数记录下gc日志会非常便于故障排查。也可以进行日常JVM监控。
4、监控类的加载情况:-XX:+TraceClassLoading
使用这个参数可以监控java程序加载的类。

4、如何解决OOM异常?

1、要解决OOM异常或heap space的异常,一般的手段是首先通过内存映像分析工具(如Eclipse Memory Analyzer)对dump 出来的堆转储快照进行分析,重点是确认内存中的对象是否是必要的,也就是要先分清楚到底是出现了内存泄漏(Memory Leak)还是内存溢出(Memory Overflow)。

2、如果是内存泄漏,可进一步通过工具查看泄漏对象到GC Roots 的引用链。于是就能找到泄漏对象是通过怎样的路径与GC Roots 相关联并导致垃圾收集器无法自动回收它们的。掌握了泄漏对象的类型信息,以及GC Roots 引用链的信息,就可以比较准确地定位出泄漏代码的位置。

3、如果不存在内存泄漏,换句话说就是内存中的对象确实都还必须存活着,那就应当检查虚拟机的堆参数(-Xmx 与-Xms),与机器物理内存对比看是否还可以调大,从代码上检查是否存在某些对象生命周期过长、持有状态时间过长的情况,尝试减少程序运行期的内存消耗。

版权声明:本文为CSDN博主「zj_daydayup」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u012556994/article/details/81264962

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值