JVM性能优化

原理

JVM在执行Java程序时会把它所管理的内存划分为若干个不同的运行时数据区域,主要包括:程序计数器、方法区、虚拟机栈、本地方法栈和堆:

  1. 程序计数器可以看作时当前线程所执行的字节码的行号指示器。
  2. 方法区用于存储被JVM加载的类信息、常量、静态变量等数据。
  3. 虚拟机栈存储的时Java方法执行的线程内存模型,每一个方法被调用到执行完毕的过程,就对应一个栈帧在虚拟机栈中从入栈到出栈的过程。
  4. 本地方法栈和虚拟机栈的功能相同,差别是本地方法栈只为本地方法调用服务。
  5. 堆是JVM管理内存中占用比例最大的一块,用于存储Java程序对象实例,几乎所有的对象实例内存都在这里分配。从内存回收角度和经典垃圾收集器分带理论上看,堆内存空间一般被分为:新生代、老年代、永久代、Eden空间、From/To Survivor等区域。各代功能和划分说明可以参考:Java虚拟机:JVM内存分代策略 - 风中程序猿 - 博客园 。

针对堆空间的优化是Java性能调优的重点之一。如果没有设置JVM堆空间大小,JVM会根据服务器物理内存大小设置默认堆大小的值。例如,在64位的服务器端,当物理内存小于192MB时,JVM堆大小默认选为物理内存的一半;当物理内存大192MB且小于128GB时,JVM堆大小默认选为物理内存的四分之一;当物理内存大于等于128GB时,都为32GB。通常情况下,Java应用程序的会通过参数指定堆大小,具体方法下文会有说明。

应用程序选用多大的堆空间大小及配比,一般要根据程序的GC情况和服务器内存资源进行综合评估,是个循序渐进不断优化的过程,如果垃圾回收(GC)频繁触发,可以尝试增加堆空间缓解。

推荐配置原则:

  1. 应用程序运行时,计算老年代存活对象的占用空间大小X。程序整个堆大小(Xmx和Xms)设置为X的3~4倍;永久代PermSize和MaxPermSize设置为X的1.2~1.5倍。年轻代Xmn的设置为X的1~1.5倍。老年代内存大小设置为X的2~3倍。
  2. JDK官方建议年轻代占整个堆大小空间的3/8左右。
  3. 完成一次Full GC后,应该释放出70%的堆空间(30%的空间仍然占用)。

修改方式

在Java应用程序启动时,添加如下参数并设置大小:

-Xmx

设置JVM最大可用堆内存大小。

-Xms

设置初始堆大小,一般和Xmx保持一致。

-Xmn

设置年轻代堆大小。

-Xss

设置每个线程的堆大小。JDK 1.5以后每个线程堆栈大小默认为1MB,1.5以前为256K。

-XX:NewRatio=

设置年轻代(包括Eden和两个Survivor区)与老年代的比值(不包括永久代)。如设置为4,则年轻代与老年代所占比值为1:4,年轻代占整个堆栈的1/5。

-XX:SurvivorRatio=

设置年轻代中Eden区与Survivor区的大小比值。如设置为4,则两个Survivor区与一个Eden区的比值为2:4,一个Survivor区占整个年轻代的1/6。

-XX:MaxPermSize=

设置永久代堆大小。

举例:

java -Xmx3600m -Xms3600m -Xmn2g -Xss128k

设置最大堆空间为3600MB,初始化堆大小为3600MB,年轻代大小为2GB,线程堆大小为128KB。

选择合适的垃圾回收器

原理

垃圾回收器是内存回收的具体实现,JDK自带的垃圾回收器已经完成集成垃圾回收和清理算法,业务程序可以通过设置参数选择垃圾回收器,虚拟机用到的7种经典的垃圾回收器如下表。根据适用内存区域不同,JDK自带的垃圾回收器可分为新生代回收器和老年代回收器,两者可以配合使用。新生代回收器用于堆空间中新生代区域的垃圾回收,老年代回收器用于堆空间中老年代区域的垃圾回收。G1是一种新型的堆内垃圾收集器,既可以用于新生代也可以用于老年代垃圾回收。

下表列举了经典的7种垃圾回收器的说明和功能分类:

名称

说明

收集模式

分代适用类型

Serial

单线程串行收集器

串行收集器

新生代

ParNew

多线程并行Serial收集器

并行收集器

新生代

Parallel Scavenge

并行吞吐量优先收集器

并行收集器

新生代

Serial Old

Serial单线程收集器老年代版本

串行收集器

老年代

CMS(Concurrent Mark Sweep)

并行最短停顿时间收集器

并发收集器

老年代

Parallel Old

Parallel Scavenge并行收集器老年代版本

并行收集器

老年代

G1

面向局部收集和基于Region内存布局的新型低延时收集器

并发/并行收集器

新生代/老年代

下图展示了新生代GC和老年代GC配合使用方法,有连线的表示可以配合使用。注意ParNew和Parallel Old是不能同时使用的。

垃圾回收器的选择方法没有通用的准则,要结合项目应用的实际并对GC运行数据的检测来决定。

根据收集模式经典垃圾回收器可分为三类:串行收集器、并行收集器、并发收集器。串行收集器只适用于小数据量的情况,选择主要针对并行收集器和并发收集器。默认情况下,JDK1.5以前都是使用串行收集器,如果想使用其他收集器需要在启动时加入相应参数。JDK1.5以后,JVM会根据当前系统配置进行判断。

垃圾回收器选择建议:

  • 业务应用对吞吐量要求较高,对响应时间没有特别要求的,推荐使用并行收集器。如:科学计算和后台处理程序等等。
  • 对响应时间要求较高的中大型应用程序,推荐使用并发收集器。如:web服务器等。
  • 对应JDK版本1.8以上,多CPU处理器且内存资源不是瓶颈,建议优先考虑使用G1回收器。
  • 单线程应用使用串行收集器。

修改方式

以下表格汇总了各种回收器的分类、特点和修改参数:

名称

修改参数

特点

Serial

-XX:+UseSerialGC

用于新生代的单线程收集器,采用复制算法进行垃圾收集。Serial 进行垃圾收集时,所有的用户线程必须暂停(Stop The World)。

ParNew

-XX:+UseParNewGC

Serial的多线程版本,在单核CPU环境并不会比Serial更优,它默认开启的收集线程数和CPU核数,可以通过-XX:ParallelGCThreads来设置垃圾收集的线程数。

Parallel Scavenge

-XX:+UseParallelGC jdk1.7、jdk1.8 新生代默认使用

用于新生代的多线程收集器,ParNew的目标是尽可能缩短垃圾收集时用户线程的停顿时间,Parallel Scavenge的目标是达到一个可控制的吞吐量。通过-XX:MaxGCPauseMillis来设置收集器尽可能在多长时间内完成内存回收,通过-XX:GCTimeRatio来精确控制吞吐量。

Serial Old

-XX:+UseSerialOldGC

Serial的老年代版本,采用标记-整理算法单线程收集器。

CMS

-XX:+UseConMarkSweepGC

一种以最短回收停顿时间为目标的收集器,尽量做到最短用户线程停顿时间。CMS是基于标记-清除算法,所以垃圾回收后会产生空间碎片,通过-XX:UseCMSCompactAtFullCollection开启碎片整理(默认开启)。用-XX:CMSFullGCsBeforeCompaction设置执行多少次不压缩(不进行碎片整理)的Full GC之后,跟着来一次带压缩(碎片整理)的Full GC。-XX:ParallelCMSThreads:设定CMS的线程数量。

Parallel Old

-XX:+UseParallelOldGC jdk1.7、jdk1.8老年代默认使用

Parallel Scavenge的老年代版本,使用-XX:ParallelGCThreads限制线程数量。

G1

-XX:+UseG1GC

jdk1.7以后才提供,jdk1.9默认

一款全新的收集器,兼顾并行和并发功能,能充分利用多CPU资源,运行期间不会产生内存碎片。通过-XX:ParallelGCThreads设置限制线程数量;-XX:MaxGCPauseMillis设置最大停顿时间。

关于信创国产平台的JDK的说明要点:

1. TongWeb6支持JDK6及以上版本,TongWeb7支持JDK7及以上版本。

2. 目前国产平台多以Open JDK8为主。统信UOS操作系统带Open JDK11。

3. 国产平台Open JDK由操作系统自带,在安装操作系统时,别忘记安装JDK。

注:国产平台有龙芯、飞腾、鲲鹏、申威、海光、兆芯等CPU,所以国内没有统一提供这些平台版本的OpenJDK,通常由国产操作系统自带。

常见问题:

1. 考虑JDK版本,除TongWeb外,还要考虑部署在TongWeb上的应用支持的JDK版本?

2. 个别情况应用需要JDK5,6,7低版本的支持,但目前国产平台基本不提供这些低版本JDK。

3. 国产各个平台没有提供对外的JDK下载地址,不像Oralce JDK提供统一对外下载:Java Downloads | Oracle 一定要嘱咐在装操作系统时装好JDK。

4. 实在不行,海光、兆芯平台可下载Oracle JDK x86版本,飞腾、鲲鹏可下载Oracle JDK arm版本试试,但不保证兼容性。华为提供毕昇JDK。

5. 某些国产平台提供JDK问题分析帮助, 如:龙芯JDK崩溃,可看官网

龙芯开源社区

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值