JVM最详细知识点笔记-监控与性能调优篇

JVM最详细知识点笔记-监控与性能调优篇,第1张

JVM最详细知识点笔记-监控与性能调优篇 性能监控与调优 一、概述 1.1 基本概述

监控的依据

运行日志异常堆栈GC日志线程快照堆转储快照

调优的方向

合理地编写代码充分并合理的使用硬件资源合理地进行JVM调优 1.2 性能优化的步骤 1.2.1 发现问题:性能监控

一种以非强行或者入侵方式收集或查看应用运营性能数据的活动。

监控通常是指一种在生产、质量评估或者开发环境下实施的带有预防或主动性的活动。

当应用相关干系人提出性能问题却没有提供足够多的线索时,首先我们需要进行性能监控,随后是性能分析。

常见的问题:

GC频繁cpu load过高OOM内存泄漏死锁程序响应时间较长 1.2.2 排查问题:性能分析

一种以侵入方式收集运行性能数据的活动,它会影响应用的香吐量或响应性。

性能分析是针对性能问题的答复结果,关注的范围通常比性能监控更加集中。

性能分析很少在生产环境下进行,通常是在质量评估、系统测试或者开发环境下进行,是性能监控之后的步骤。

常见方法:

打印GC日志,通过 GCviewer 或者 http://gceasy.io 来分析日志信息灵活运用命令行工具,jstack,jmap,jinfo 等dump出堆文件,使用内存分析工具分析文件使用阿里Arthas,或 jconsole,JVisualVM来实时查看JVM状态jstack查看堆栈信息 1.2.3 解决问题:系能调优

一种为改善应用响应性或吞吐量而更改参数、源代码、属性配置的活动,性能调优是在性能监控、性能分析之后的活动。

1.3 性能评价 / 测试指标 1.3.1 停顿时间

提交请求和返回该请求的响应之间使用的时间

在垃圾回收环节中:

暂停时间:执行垃圾收集时,程序的工作线程被暂停的时间。

1.3.2 吞吐量

对单位时间内完成的工作量(请求)的量度

在GC中:

运行用户代码的时间占总运行时间的比例(总运行时间:程序的运行时间+内存回收的时间)

吞吐量为 1-1/(1+n)。-XX:GCTimeRatio=n

1.3.3 并发数

同一时刻,对服务器有实际交互的请求数

1.3.4 内存占用

Java堆区所占的内存大小

二、JVM 监控及诊断工具-命令行 2.1 概述

性能诊断是软件工程师在日常工作中需要经常面对和解决的问题,在用户体验至上的今天,解决好应用的性能问题能带来非常大的收益。

Java 作为最流行的编程语言之一,其应用性能诊断一直受到业界广泛关注。可能造成Java应用出现性能问题的因素非常多,例如线程控制、磁盘读写、数据库访问、网络I/0、垃圾收集等。想要定位这些问题,一款优秀的性能诊断工具必不可少。

使用数据说明问题,使用知识分析问题,使用工具处理问题。无监控、不调优! 2.2 jps:查看正在运行的 java 进程

基本信息

jps (Java Process Status) :

显示指定系统内所有的HotSpot虚拟机进程(查看虚拟机进程信息),可用于查询正在运行的虚拟机进程。

说明:对于本地虚拟机进程来说,进程的本地虚拟机ID与 *** 作系统的进程ID是一致的,是唯一的。

基本语法

jps [options] [hostid]

option参数:

-q:仅仅显示LVMId (local virtual machine id),即本地虚拟机唯一id。不显示主类的名称等-l:输出应用程序主类的全类名或如果进程执行的是jar包,则输出jar完整路径-m:输出虚拟机进程启动时传递给主类main()的参数-v:列出虚拟机进程启动时的JVM参数。比如: -Xms20m -Xmx50m是启动程序指定的jvm参数。(只能查看设置过的)

补充:如果某Java进程关闭了默认开启的 UsePerfData 参数(即使用参数**-XX:-UsePerfData**),那么jps命令(以及下面介绍的jstat)将无法探知该Java进程。

2.3 jstat:查看 JVM 统计信息

基本信息

jstat(VM Statistics Monitoring Tool):用于监视虚拟机各种运行状态信息的命令行工具。它可以显示本地或者远程虚拟机进程中的类装载、内存、垃圾收集、JIT编译等运行数据。

在没有GUI图形界面,只提供了纯文本控制台环境的服务器上,它将是运行期定位虚拟机性能问题的首选工具。常用于检测垃圾回收问题以及内存泄漏问题。

基本语法

jstat	-

option参数:

类装载相关的:

-class:显示classLoader的相关信息:类的装载、卸载数量、总空间、
类装载所消耗的时间等 垃圾回收相关的:

-gc:显示与GC相关的堆信息。包括Eden区、两个Survivor区、老年代、永久代等的容量、已用空间、GC时间合计等信息。-gccapacity:显示内容与-gc基本相同,但输出主要关注Java堆各个区域使用到的最大、最小空间。-gcutil:显示内容与-gc基本相同,但输出主要关注已使用空间占总空间的百分比。-gccause:与 -gcutil 功能一样,但是会额外输出导致最后一次或当前正在发生的GC产生的原因。-gcnew:显示新生代GC状况-gcnewcapacity:显示内容与-gcnew基本相同,输出主要关注使用到的最大、最小空间-geold:显示老年代GC状况-gcoldcapacity:显示内容与-gcold基本相同,输出主要关注使用到的最大、最小空间-gcpermcapacity:显示永久代使用到的最大、最小空间。 JIT相关的:

-compiler:显示JIT编译器编译过的方法、耗时等信息-printcompilation:输出已经被JIT编译的方法

经验

我们可以比较Java进程的启动时间以及总GC时间(GCT 列),或者两次测量的间隔时间以及总GC时间的增量,来得出GC时间占运行时间的比例。

如果该比例超过20%,则说明目前堆的压力较大;如果该比例超过90%,则说明堆里几乎没有可用空间,随时都可能抛出OOM异常。

补充

jstat还可以用来判断是否出现内存泄漏。

第1步:

在长时间运行的Java程序中,我们可以运行jstat命令连续获取多行性能数据,并取这几行数据中ou 列(即已占用的老年代内存)的最小值。

第2步:

然后,我们每隔一段较长的时间重复一次上述 *** 作,来获得多组OU最小值。如果这些值呈上涨趋势,则说明该Java程序的老年代内存已使用量在不断上涨,这意味着无法回收的对象在不断增加,因此很有可能存在内存泄漏。

2.4 jinfo:实时查看和修改 JVM 配置参数

jinfo(Configuration Info for Java)

查看虚拟机配置参数信息,也可用于调整虚拟机的配置参数。

在很多情况下,Java应用程序不会指定所有的Java虚拟机参数。而此时,开发人员可能不知道某一个具体的Java虚拟机参数的默认值。在这种情况下,可能需要通过查找文档获取某个参数的默认值。这个查找过程可能是非常艰难的。但有了jinfo工具,开发人员可以很方便地找到Java虚拟机参数的当前值。

基本语法

jinfo [ options ] pid
options 选项选项说明no option输出全部的参数和系统属性-flag name输出对应名称的参数-flag [±]name开启或者关闭对应名称的参数只有被标记为manageable的参数才可以被动态修改-flag name=value设定对应名称的参数-flags输出全部的参数-sysprops输出系统属性

关于修改

不是所有的参数都能修改,只有被标志为 manageable 的才能被修改

可以查看被标记为 manageable 的参数

java -XX:+PrintFlagsFinal -version | grep manageable
2.5 jmap:导出内存映像文件&内存使用状况

jmap(JVM Memory Map):

作用一方面是获取dump文件(堆转储快照文件,二进制文件),它还可以获取目标Java进程的内存相关信息,包括Java堆各区域的使用情况、堆中对象的统计信息、类加载信息等。

基本语法

jmap [option] jmap [option]

option

使用1:导出内存映像文件

dump文件中包含的信息:

所有的对象所有的类GC Roots虚拟机栈和局部变量表

    手动导出
jmap -dump:format=b,file=   # 导出所有的对象

jmap -dump:live,format=b,file=   # 导出存活的对象,更加的常用
    自动导出

当程序发生0OM退出系统时,一些瞬时信息都随着程序的终止而消失,而重现oOM问题往往比较困难或者耗时。此时若能在OOM时,自动导出dump文件就显得非常迫切。

-XX:+HeapDumponoutOfMemoryError				在程序发生OOM时,导出应用程序的当前堆快照。
-XX:+HeapDumpBeforeFullGC

-XX:HeapDumpPath=						可以指定堆快照的保存位置。

使用2:显示堆内存相关的信息

jmap -heap pid			# 堆空间的分配信息,以及占用情况

jmap -histo pid			# 对象占用的空间大小
2.6 jhat:JDK 自带堆分析工具

jhat ( JVM Heap Analysis Tool):

Sun JDK提供的jhat命令与jmap命令搭配使用,用于分析jmap生成的heap dump文件(堆转储快照)。

jhat内置了一个微型的HTTP/HTML服务器,生成dump文件的分析结果后,用户可以在浏览器中查看分析结果(分析虚拟机转储快照信息)。

使用了jhat命令,就启动了一个http服务,端口是7000,即http://localhost:7000/,就可以在浏览器里分析。

说明:jhat命令在DK9、JDK10中已经被删除,官方建议用VisualVM代替。

基本使用:

jhat 
2.7 jstack:打印 JVM 中线程快照

jstack(JM Stack Trace):用于生成虚拟机指定进程当前时刻的线程快照(虚拟机堆栈跟踪)。线程快照就是当前虚拟机内指定进程的每一条线程正在执行的方法堆栈的集合。

生成线程快照的作用:可用于定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间等待等问题。这些都是导致线程长时间停顿的常见原因。当线程出现停顿时,就可以用jstack显示各个线程调用的堆栈情况。

在 jstack 中需要关注:

死锁,Deadlock(重点关注)等待资源,waiting on condition(重点关注)等待获取监视器,waiting on monitor entry(重点关注)阻塞,Blocked(重点关注)执行中,Runnable暂停,Suspended对象等待中,object.wait()或TIMED_WAITING停止,Parked

基本使用

jstack option pid

jstack管理远程进程的话,需要在远程程序的启动参数中增加

-Djava.rmi .server.hostname=……

-Dcom.sun.management .jmxremote

-Dcom.sun.management.jmxremote.port=8888

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

2.8 jcmd:多功能命令行

在JDK 1.7以后,新增了一个命令行工具jcmd。

它是一个多功能的工具,可以用来实现前面除了jstat之外所有命令的功能。比如:用它来导出堆、内存使用、查看Java进程、导出线程信息、执行GC、JVM运行时间等。

基本使用

jcmd -l				# 查看java进程pid,类似于 jps -m
jcmd  help		# 查看该进程有哪些可用的命令
三、JVM 监控工具-GUI 3.1 工具概述

使用命令行会有一些局限性:

    无法获取方法级别的分析数据,如方法间的调用关系、各方法的调用次数和调用时间等(这对定位应用性能瓶颈至关重要)。要求用户登录到目标Java应用所在的宿主机上,使用起来不是很方便。分析数据通过终端输出,结果展示不够直观。

图形化综合诊断工具:

jdk自带

jconsole:JDK自带的可视化监控工具。查看Java应用程序的运行概况、监控堆信息、永久区(或元空间)使用情况、类加载情况等

位置:jdk binljconsole.exe Visual VM:Visual VM是一个工具,它提供了一个可视界面,用于查看Java虚拟机上运行的基于Java技术的应用程序的详细信息。

位置:jdk binljvisualvm.exe JMC:Java Mission Control,内置Java Flight Recorder。能够以极低的性能开销收集Java虚拟机.的性能数据。

第三方工具

MAT: MAT(Memory Analyzer Tool)是基于Eclipse的内存分析工具,是一个快速、功能丰富的Java heap分析工具,它可以帮助我们查找内存泄漏和减少内存消耗

Eclipse的插件形式 JProfiler:商业软件,需要付费。功能强大。

与VisualVM类似 Arthas:Alibaba开源的Java诊断工具。深受开发者喜爱。Btrace:Java运行时追踪工具。可以在不停机的情况下,跟踪指定的方法调用、构造函数调用和系统内存等信息。 3.2 Jconsole

从Java5开始,在JDK中自带的java监控和管理控制台。用于对JVM中内存、线程和类等的监控,是一个基于JMX(java management extensions)的GUI性能监控工具。

其中线程监控还可以检查死锁

3.3 Visual-VM

概述

Visual VM是一个功能强大的多合一故障诊断和性能监控的可视化工具。它集成了多个JDK命令行工具,使用Visual VM可用于显示虚拟机进程及进程的配置和环境信息(jps,jinfo),监视应用程序的CPU、GC、堆、方法区及线程的信息(jstat、jstack)等,甚至代替JConsole。在JDK 6 Update 7以后,Visual VM便作为JDK的一部分发布(VisualVM 在JDK/bin目录下),即:它完全免费。此外,Visual VM也可以作为独立的软件安装

基本功能

    生成/读取内存快照

    查看JVM参数和系统属性

    查看运行中的虚拟机进程

    生成/读取线程快照

    程序资源的实时监控

    其他功能

    JMX代理连接远程环境监控CPU分析和内存分析

3.4 eclipse MAT

MAT可以分析dump文,相比于visual-vm更加详细

一般能获取以下信息:

所有的对象信息,包括对象实例、成员变量、存储于栈中的基本类型值和存储于堆中的其他对象的引用值。所有的类信息,包括classloader、类名称、父类、静态变量等GCRoot到所有的这些对象的引用路径线程信息,包括线程的调用栈及此线程的线程局部变量(TLS) 3.5 JProfiler

在运行Java的时候有时候想测试运行时占用内存情况,这时候就需要使用测试工具查看了。在eclipse里面有Eclipse Memory Analyzer tool(MAT)插件可以测试,而在IDEA中也有这么一个插件,就是JProfiler。

特点:

使用方便、界面 *** 作友好―(简单且强大)对被分析的应用影响小(提供模板)CPU,Thread ,Memory分析功能尤其强大支持对jdbc,noSql,jsp, servlet,socket等进行分析支持多种模式(离线,在线)的分析支持监控本地、远程的JVM跨平台,拥有多种 *** 作系统的安装版本

数据采样方式

JProfier数据采集方式分为两种:Sampling(样本采集)和Instrumentation(重构模式)

Instrumentation:这是JProfiler全功能模式。在class加载之前,JProfier把相关功能代码写入到需要分析的class的bytecode中,对正在运行的jvm有一定影响。

优点:功能强大。在此设置中,调用堆栈信息是准确的。缺点:若要分析的class较多,则对应用的性能影响较大,CPU开销可能很高(取决于Filter的控制)。因此使用此模式一般配合Filter使用,只对特定的类或包进行分析。

Sampling:类似于样本统计,每隔一定时间(5ms )将每个线程栈中方法栈中的信息统计出来。

优点:对CPU的开销非常低,对应用影响小(即使你不配置任何Filter)缺点:一些数据/特性不能提供(例如:方法的调用次数、执行时间) 3.6 内存泄漏问题 3.6.1 内存泄漏的理解与分类

何为内存泄漏

可达性分析算法来判断对象是否是不再使用的对象,本质都是判断一个对象是否还被引用。那么对于这种情况下,由于代码的实现不同就会出现很多种内存泄漏问题(让JVM误以为此对象还在引用中,无法回收,造成内存泄漏)。

是否还被使用? 是是否还被需要? 否

严格来说,只有对象不会再被程序用到了,但是GC又不能回收他们的情况,才叫内存泄漏。

但实际情况很多时候一些不太好的实践(或疏忽)会导致对象的生命周期变得很长甚至导致oOM,也可以叫做宽泛意义上的“内存泄漏”。

内存泄露与内存溢出的关系

1.内存泄漏(memory leak )

申请了内存用完了不释放,比如一共有1024M的内存,分配了512M 的内存一直不回收,那么可以用的内存只有512M 了,仿佛泄露掉了一部分;

通俗一点讲的话,内存泄漏就是【占着茅坑不拉shi】。

2.内存溢出(out of memory)

申请内存时,没有足够的内存可以使用;

通俗一点儿讲,一个厕所就三个坑,有两个站着茅坑不走的(内存泄漏),剩下最后一个坑,厕所表示接待压力很大,这时候一下子来了两个人,坑位(内存)就不够了,内存泄漏变成内存溢出了。

可见,内存泄漏和内存溢出的关系:内存泄漏的增多,最终会导致内存溢出。

3.6.2 内存泄露的8种情况 3.6.2.1 静态集合类

静态集合类,如HashMap、linkedList等等。如果这些容器为静态的,那么它们的生命周期与JVM程序一致,则容器中的对象在程序结束之前将不能被释放,从而造成内存泄漏。简单而言,长生命周期的对象持有短生命周期对象的引用,尽管短生命周期的对象不再使用,但是因为长生命周期对象持有它的引用而导致不能被回收。

public class MemoryLeak {
	static List list = new ArrayList();
    
	public void oomTests() {
		object obj = new object();//局部变量list.add(obj);
	}
}
3.6.2.2 单例模式

单例模式,和静态集合导致内存泄露的原因类似,因为单例的静态特性,它的生命周期和JVM的生命周期一样长,所以如果单例对象如果持有外部对象的引用,那么这个外部对象也不会被回收,那么就会造成内存泄漏。

3.6.2.3 内存类持有外部类

内部类持有外部类,如果一个外部类的实例对象的方法返回了一个内部类的实例对象。

这个内部类对象被长期引用了,即使那个外部类实例对象不再被使用,但由于内部类持有外部类的实例对象,这个外部类对象将不会被垃圾回收,这也会造成内存泄漏。

3.6.2.4 各种连接:数据库、网络、IO

在对数据库进行 *** 作的过程中,首先需要建立与数据库的连接,当不再使用时,需要调用close方法来释放与数据库的连接。只有连接被关闭后,垃圾回收器才会回收对应的对象。

否则,如果在访问数据库的过程中,对Connection、Statement或ResultSet不显性地关闭,将会造成大量的对象无法被回收,从而引起内存泄漏。

3.6.2.5 变量不合理的作用域

变量不合理的作用域。一般而言,一个变量的定义的作用范围大于其使用范围,很有可能会造成内存泄漏。另一方面,如果没有及时地把对象设置为null,很有可能导致内存泄漏的发生。

public class UsingRandom {
	private String msg;
	public void receiveMsg(){
        // private String msg;
		readFromNet();//从网络中接受数据保存到msg中saveDB();/l 把msg保存到数据库中
		//msg = null;
	}
}

如上面这个伪代码,通过readFromNet方法把接受的消息保存在变量msg中,然后调用saveDB方法把msg的内容保存到数据库中,此时msg已经就没用了,由于msg的生命周期与对象的生命周期相同,此时msg还不能回收,因此造成了内存泄漏。

实际上这个msg变量可以放在receiveMsg方法内部,当方法使用完,那么msg的生命周期也就结束,此时就可以回收了。还有一种方法,在使用完msg后,把msg设置为null,这样垃圾回收器也会回收msg的内存空间。

3.6.2.6 改变哈希值

改变哈希值,当一个对象被存储进HashSet集合中以后,就不能修改这个对象中的那些参与计算哈希值的字段了。

否则,对象修改后的哈希值与最初存储进HashSet集合中时的哈希值就不同了,在这种情况下,即使在contains方法使用该对象的当前引用作为的参数去HashSet集合中检索对象,也将返回找不到对象的结果,这也会导致无法从HashSet集合中单独删除当前对象,造成内存泄漏。

这也是 String为什么被设置成了不可变类型,我们可以放心地把String存入 HashSet,或者把String当做HashMap 的 key 值;
当我们想把自己定义的类保存到散列表的时候,需要保证对象的 hashCode不可变。

3.6.2.7 缓存泄露

内存泄漏的另一个常见来源是缓存,一旦你把对象引用放入到缓存中,他就很容易遗忘。比如:之前项目在一次上线的时候,应用启动奇慢直到夯死,就是因为代码中会加载一个表中的数据到缓存(内存)中,测试环境只有几百条数据,但是生产环境有几百万的数据。

对于这个问题,可以使用WeakHashMap代表缓存,此种Map的特点是,当除了自身有对key的引用外,此key没有其他引用那么此map会自动丢弃此值。

3.6.2.8 监听器和回调

内存泄漏另一个常见来源是监听器和其他回调,如果客户端在你实现的API中注册回调,却没有显示的取消,那么就会积聚。需要确保回调立即被当作垃圾回收的最佳方法是只保存它的弱引用,例如将他们保存成为WeakHashMap中的键。

四、JVM运行时参数 4.1 JVM 参数选项类型

标准参数选项

以 “-” 开头

通过 java -help 查看

-X参数选项

以 “-X” 开头

运行 java -X 查看

-XX参数选项

以 “-XX” 开头

分类:

boolean类型格式

-XX:+表示启用option属性-XX:-表示禁用option属性 key-value类型格式

子类型1:数值型格式-XX:=子类型2:非数值型格式-XX:= 4.2 添加 JVM 参数选项

通过Tomcat运行war包

Linux系统下可以在tomcat/bin/catalina.sh中添加类似如下配置:JAVA_OPTS="-Xms512M -Xmx1024M"

windows系统下在catalina.bat中添加类似如下配置:set “JAVA_OPTS=-Xms512M -Xmx1024M”

程序运行过程

使用jinfo -flag = 设置非Boolean类型参数

使用jinfo -flag [+/-] 设置Boolean类型参数

4.3 常用的 JVM 参数选项

打印设置的 XX 选项及值

-XX:+PrintCommandLineFlags可以让在程序运行前打印出用户手动设置或者JVM自动设置的XX选项-XX:+PrintFlagsInitial表示打印出所有XX选项的默认值-XX:+ PrintFlagsFinal表示打印出XX选项在运行程序时生效的值-XX:+PrintvMOptions打印JVM的参数

堆、栈、方法区等内存大小设置

-Xss128k 设置每个线程的栈大小为128k 堆

-Xms3550m 等价于-XX:InitialHeapSize,设置JVM初始堆内存为355OM-Xmx3550m 等价于-XX:MaxHeapSize,设置JVM最大堆内存为355OM-Xmn2g 设置年轻代大小为2G,官方推荐配置为整个堆大小的3/8-XX:NewSize=1024m 设置年轻代初始值为1024M-XX:MaxNewSize=1024m 设置年轻代最大值为1024M-XX:SurvivorRatio=8 设置年轻代中Eden区与一个Survivor区的比值,默认为8-XX:+UseAdaptiveSizePolicy 自动选择各区大小比例-XX:NewRatio=4 设置老年代与年轻代(包括1个Eden和2个Survivor区)的比值-XX:PretenureSizeThreadshold=1024

只对Serial、ParNew收集器有效设置让大于此阈值的对象直接分配在老年代,单位为字节 -XX:MaxTenuringThreshold=15

新生代次MinorGC后,还存活的对象年龄+1,当对象的年龄大于设置的这个值时就进入老年代默认值为15 -XX:+PrintTenuringDistribution 让JVM在每次MinorGC后打印出当前使用的Survivor中对象的年龄分布-XX:TargetSurvivorRatio 表示MinorGC结束后Survivor区域中占用空间的期望比例 永久代

-XX:PermSize=256m 设置永久代初始值为256M-XX:MaxPermSize=256m 设置永久代最大值为256M 元空间

-XX:metaspacesize 初始空间大小-XX:Maxmetaspacesize 最大空间,默认没有限制-XX:+UseCompressedOops 压缩对象指针-XX:+UseCompressedClassPointers 压缩类指针-xX:CompressedClassSpacesize 设置Klass metaspace的大小,默认1G 直接内存

-XX:MaxDirectMemorySize 指定DirectMemory容量,若未指定,则默认与Java堆最大值一样

OutOfMemory 相关选项

-XX:+HeapDumponOutOfMemoryError 表示在内存出现OOM的时候,把Heap转存(Dump)到文件以便后续分析-XX:+HeapDumpBeforeFullGC 表示在出现FulIGC之前,生成Heap转储文件-XX:HeapDumpPath= 指定heap转存文件的存储路径 -XX:onOutOfMemoryError 指定一个可行性程序或者脚本的路径,当发生OOM的时候,去执行这个脚本

垃圾收集器相关选项

-XX:+PrintCommandLineFlags 查看命令行相关参数(包含使用的垃圾收集器)Serial

Serial收集器作为HotSpot中Client模式下的默认新生代垃圾收集器。Serial old是运行在Client模式下默认的老年代的垃圾回收器。-XX:+UseSerialGc指定年轻代和老年代都使用串行收集器。等价于新生代用serial GC,且老年代用Serial old GC。可以获得最高的单线程收集效率。 ParNew

-XX:+UseParNewGC手动指定使用ParNew收集器执行内存回收任务。它表示年轻代使用并行收集器,不影响老年代。-XX: Paralle1GCThreads=N限制线程数量,默认开启和CPU数据相同的线程数。 Parallel

-XX:+UseParallelGC 手动指定年轻代使用Parallel并行收集器执行内存回收任务。-XX:+UseParallel0ldGC手动指定老年代都是使用并行回收收集器。

分别适用于新生代和老年代。默认jdk8是开启的。上面两个参数,默认开启一个,另一个也会被开启。(互相激活) -XX:ParallelGCThreads 设置年轻代并行收集器的线程数。一般地,最好与CPU数量相等,以避免过多的线程数影响垃圾收集性能。

在默认情况下﹒当CPU 数量小于8个, ParallelGCThreads 的值等于CPU 数量。当CPU数量大于8个,ParallelGCThreads的值等于3+[5*CPU Count]/8] 。 -XX:MaxGCPauseMillis 设置垃圾收集器最大停顿时间(即STw的时间)。单位是毫秒。

为了尽可能地把停顿时间控制在MaxGCPauseMills以内,收集器在工作时会调整Java堆大小或者其他一些参数。对于用户来讲,停顿时间越短体验越好。但是在服务器端,我们注重高并发,整体的吞吐量。所以服务器端适合Paralle1,进行控制。该参数使用需谨慎。 -XX:GCTimeRatio垃圾收集时间占总时间的比例(= 1 / (N + 1))。用于衡量吞吐量的大小。

取值范围(e,100)。默认值99,也就是垃圾回收时间不超过1%。与前一个-XX:MaxGCPauseMillis参数有一定矛盾性。暂停时间越长,Radio参数就容易超过设定的比例。 -XX:+UseAdaptivesizePolicy 设置Parallel Scavenge收集器具有自适应调节策略 CMS

-XX:+UseConcMarkSweepGC手动指定使用cMS收集器执行内存回收任务。

开启该参数后会自动将-XX:+UseParNewGC打开。即:ParNew(Young区用)+CNS(01d区用)+Serial old的组合。 -XX:CMSInitiatingOccupanyFraction设置堆内存使用率的阀值,一旦达到该阈值,便开始进行回收。

JDK5及以前版本的默认值为68,即当老年代的空间使用率达到68%时,会执行一次CMS回收。JDK6及以上版本默认值为92%如果内存增长缓慢,则可以设置一个稍大的值,大的阈值可以有效降低CNS的触发频率,减少老年代回收的次数可以较为明显地改善应用程序性能。反之,如果应用程序内存使用率增长很快,则应该降低这个阈值,以避免频繁触发老午代串行收集器。因此通过该选项便可以有效降低Full GC的执行次数。 -XX:+UseCMSCompactAtFullCollection 用于指定在执行完Full GC后对内存空间进行压缩整理,以此避免内存碎片的产生。不过由于内存压缩整理过程无法并发执行,所带来的问题就是停顿时间变得更长了。-XX:CISFu1lGCsBeforeCompaction 设置在执行多少次Full GC后对内存空间进行压缩整理。-XX:Paralle1CMSThreads设置CMS的线程数量。

CNS默认启动的线程数是(ParallelGCThreads+3)/4,ParallelGCThreads是年轻代并
行收集器的线程数。当CPU资源比较紧张时,受到CMS收集器线程的影响,应用程序的性能在垃圾回收阶段可能会非常糟糕。| G1

-XX:+UseG1GC

手动指定使用G1收集器执行内存回收任务。 -XX:G1HeapRegionSize

设置每个Region的大小。值是2的幂,范围是1MB到32NB之间,目标是根据最小的Java堆大小划分出约2048个区域。默认是堆内存的1/2000。 -XX:MaxGCPauseMi1lis

设置期望达到的最大GC停顿时间指标(JVM会尽力实现,但不保证达到)。默认值是200ms -XX:Paralle1GCThread

设置STW时GC线程数的值。最多设置为8 -XX:ConcGCThreads

设置并发标记的线程数。将n设置为并行垃圾回收线程数(ParallelGCThreads)的1/4左右。 -XX: InitiatingHeap0ccupancyPercent

设置触发并发GC周期的Java堆占用率阈值。超过此值,就触发GC。默认值是45。 -XXX:G1NewSizePercent、-XX:G1MaxNewSizePercent

新生代占用整个堆内存的最小百分比(默认5%)、最大百分比(默认60%) -XX:G1ReservePercent=10

保留内存区域,防止 to space ( Survivor中的to区)溢出

如何选择垃圾回收器

优先调整堆的大小让JVM自适应完成。如果内存小于100M,使用串行收集器

如果是单核、单机程序,并且没有停顿时间的要求,串行收集器

如果是多CPU、需要高吞吐量、允许停顿时间超过1秒,选择并行或者JVM自己选择

如果是多CPU、追求低停顿时间,需快速响应(比如延迟不能超过1秒,如互联网应用),使用并发收集器。官方推荐G1,性能高。现在互联网的项目,基本都是使用G1。

GC 日志相关选项

-verbose:gc

输出gc日志信息,默认输出到标准输出 -XX:+PrintGC

表示打开简化的GC日志,等同于-verbose:gc -XX:+PrintGCDetails

在发生垃圾回收时打印内存回收详细的日志,并在进程退出时输出当前内存各区域分配情况 -XX:+PrintGCTimeStamps

输出GC发生时的时间戳 -XX:+PrintGCDateStamps

输出GC发生时的时间戳(以日期的形式,如2013-05-04T21:53:59.234+0800) -XX:+PrintHeapAtGC

每一次GC前和GC后,都打印堆信息 -Xloggc:

把GC日志写入到一个文件中去,而不是打印到标准输出中

其他

-XX:+DisableExplicitGC

禁止hotspot执行System.gc(),默认禁用 -XX:ReservedCodeCacheSize=[glm|k]、-XX:InitialCodeCacheSize=[glm|k]

指定代码缓存的大小 -XX:+UseCodeCacheFlushing

使用该参数让jvm放弃一些被编译的代码,避免代码缓存被占满时JVM切换到interpreted-only的情况 -XX:+DoEscapeAnalysis

开启逃逸分析 -XX:+UseBiasedLocking

开启偏向锁 -XX:+UseLargePages

开启使用大页面 -XX:+UseTLAB

使用TLAB,默认打开 -XX:+PrintTLAB

打印TLAB的使用情况 -XX:TLABSize

设置TLAB大小

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5701932.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存