错误代码0x80071ac3(拷贝文件错误0x800700ea)[通俗易懂]

错误代码0x80071ac3(拷贝文件错误0x800700ea)[通俗易懂]JDK 17 之 JVM调优 史诗级 教程 文章目录JDK 17 之 JVM调优 史诗级 教程3.6.3 其他收集器适用场景4.1.2 如何产生dump文件4.1.2.1 JVM的配置文件中配置4….

大家好,我是讯享网,大家多多关注。

JDK 17 之 JVM调优 史诗级 教程

文章目录JDK 17 之 JVM调优 史诗级 教程3.6.3 其他收集器适用场景4.1.2 如何产生dump文件4.1.2.1 JVM的配置文件中配置4.1.2.3 第三方可视化工具生成4.5 对比调优前后指标差异5.8.1 如何启动JConsole5.8.2 如何设置JAVA程序运行时可以被JConsolse连接分析6.4.1 -XX:+PrintFlagsInitial、-XX:+PrintFlagsFinal6.4.2 -XX:+PrintCommandLineFlags6.4.4 -XX:CMSFullGCsBeforeCompaction6.4.5 -XX:HeapDumpPath6.4.6 -XX:OnOutOfMemoryError6.4.7 XX:InitialCodeCacheSize6.4.8 -XX:+UseCodeCacheFlushing1 调优层次

性能调优包括多个层次,比如架构调优、代码调优、JVM调优、数据库调优、操作系统调优。架构调优和代码调优是JVM调优的基础,其中架构调优对系统的影响最大。

2 调优指标吞吐量:运行用户代码的时间占总运行时间的行例 (总运行时间=程序的运行时间+内存回收的时间);暂停时间:执行垃圾收集时,程序的工作线程被暂停的时间;内存占用:java堆区所占的内存大小;

这三者共同构成了“不可能的三位一体”。三者的整体性能会随着技术进步越来越好。一个优秀的收藏家通常最多同时满足其中两个。

简单来说,主要有两点:

吞吐量 吞吐量优先,意味着在单位时间内,STW的时间最短暂停时间 暂停时间优先,意味这尽可能让单次STW的时间最短

在设计(或使用)一个GC算法时,我们必须确定我们的目标:一个GC算法只能瞄准两个目标中的一个(即只专注于大吞吐量或最小停顿时间),或者试图在两者之间找到一个折中。

现在标准,在最大吞吐量优先的情况下,降低停顿时间。3 JVM调优原则3.1 优先原则

架构调优和代码调优优先,JVM优化是最后手段。大多数Java应用程序不需要JVM优化。

3.2 堆设置

参数-Xms和-Xmx通常设置为相同的值,以避免在运行时不断扩展JVM内存。建议FullGC后扩展到3-4倍老龄空。

3.3 年轻代设置

参数-Xmn,1-1.5倍老龄空full GC后占用。

避免把新生代设定得太小。当把新生代设置得太小时,会带来两个问题:一是未成年GC数量频繁,二是可能导致未成年GC对象直接进入老年。当老年期内存不足时,会触发全GC。避免把新生代设置的太大,会带来两个问题:一是老龄变小,可能导致频繁执行全GC;第二,小GC执行回收的时间大大增加。

3.4 老年代设置注重低延迟的应用老年代使用并发收集器,所以其大小需要小心设置,一般要考虑并发会话率和会话持续时间等一些参数如果堆设置偏小,可能会造成内存碎片、高回收频率以及应用暂停如果堆设置偏大,则需要较长的收集时间吞吐量优先的应用 一般吞吐量优先的应用都有一个较大的年轻代和一个较小的老年代。原因是,这样可以尽可能回收掉大部分短期对象,减少中期的对象,而老年代尽可能存放长期存活对象3.5 方法区设置

基于1.7版本,永久生成:参数-XX:PermSize和-XX:maxpermsize;基于1.8版,meta 空:参数-XX:MetaspaceSize和-XX:maxmetaspacesize;它通常被设置为相同的值,以避免在运行时持续扩展。建议在FullGc后扩展到永久band 空占用率的1.2-1.5倍。

3.6 GC设置3.6.1 GC发展阶段

从jdk1.8开始,有7种不同的垃圾收集器。每个不同的垃圾收集器都有不同的特征。使用时,需要根据具体情况选择不同的垃圾收集器。

3.6.2 G1的适用场景面向服务端应用,针对具有大内存、多处理器的机器。(在普通大小的堆里表现并不惊喜)最主要的应用是需要低GC延迟并具有大堆的应用程序提供解决方案(G1通过每次只清理一部分而不是全部Region的增量式清理来保证每次GC停顿时间不会过长)在堆大小约6GB或更大时,可预测的暂停时间可以低于0.5秒用来替换掉JDK1.5中的CMS收集器,以下情况,使用G1可能比CMS好超过50% 的java堆被活动数据占用对象分配频率或年代提升频率变化很大GC停顿时间过长(大于0.5至1秒)从经验上来说,整体而言:小内存应用上,CMS大概率会优于 G1;大内存应用上,G1则很可能更胜一筹。 这个临界点大概是在 6~8G 之间(经验值)3.6.3 其他收集器适用场景如果你想要最小化地使用内存和并行开销,请选择Serial Old(老年代) + Serial(年轻代)如果你想要最大化应用程序的吞吐量,请选择Parallel Old(老年代) + Parallel(年轻代)如果你想要最小化GC的中断或停顿时间,请选择CMS(老年代) + ParNew(年轻代)4 JVM调优步骤4.1 监控分析

分析GC日志和转储文件,确定是否需要优化,并确定瓶颈问题。

4.1.1 如何生成GC日志

公共参数部分将详细解释如何生成GC日志。

4.1.2 如何产生dump文件4.1.2.1 JVM的配置文件中配置

JVM启动时添加两个参数:

#发生OOME时生成堆转储:-xx:+heapdumpoutofmemoryerror #生成堆文件地址:-xx:heapdumppath =/home/Hadoop/dump/4 . 1 . 2 . 2 jmap在发现程序异常之前,通过执行指令直接生成当前JVM的转储文件。

Jmap -dump:file=文件名。dump [pid]# 9257引用JVM的进程号JMAP-dump: format = b,file = testmap。Dump9257。第一种方法是事后方法,需要等待当前JVM出现问题后才能生成转储文件,实时性不高;第二种方式,JVM执行的时候会暂停服务,所以会对在线运行产生影响。

所以我建议第一种方式。

4.1.2.3 第三方可视化工具生成4.2 判断

如果参数设置合理,系统没有超时日志或异常信息,GC的频率不高,GC的耗时也不高,那么就不需要对GC进行优化。如果GC时间超过1-3秒,或者GC比较频繁,就必须进行优化。在下列情况下,您需要考虑JVM调优:

系统吞吐量与响应性能不高或下降;Heap内存(老年代)持续上涨达到设置的最大内存值;Full GC 次数频繁;GC 停顿时间过长(超过1秒);应用出现OutOfMemory等内存异常;应用中有使用本地缓存且占用大量内存空间;4.3 确定目标

调整的最终目标是让应用程序使用最少的硬件消耗来实现更高的吞吐量或更低的延迟。Jvm调优主要是为了优化垃圾收集器的收集性能,降低GC的频率和全GC的次数,让运行在虚拟机上的应用使用更少的内存,高吞吐量,低延迟。

下面是一些JVM调优的量化目标的例子。注意,对于不同的应用程序,JVM调优的量化目标是不同的。

堆内存使用率<=70%;老年代内存使用率<=70%;avgpause<=1秒;Full GC次数0或avg pause interval>=24小时 ;4.4 调整参数

调优通常从满足程序的内存使用要求开始,然后是时间延迟要求,最后是吞吐量要求。要在这一步的基础上不断优化,每一步都是下一步的基础,不可逆转。

4.5 对比调优前后指标差异4.6 重复以上过程4.7 应用

找到合适的参数,先在单台服务器上试用,然后将这些参数应用到所有服务器上,并进行跟进。

5 JVM调优工具5.1 jps

Jps:JVM进程状态工具Jps可以查看Java进程,相当于Linux下的ps命令,只不过它只列出Java进程。

5.1.1 使用语法

jps:列出Java程序进程ID和Main函数名称jps -q:只输出进程IDjps -m:输出传递给Java进程(主函数)的参数jps -l:输出主函数的完整路径jps -v:显示传递给Java虚拟的参数5.1.2 示例

02.png

5.2 jstat

Jstat: jvm统计监控工具Jstat可以查看Java程序运行时的相关信息,可以通过它查看堆信息的相关信息。

5.2.1 使用语法

jstat-& lt;选项& gt[-t][-h & lt;线条& gt]& lt;vmid & gt[& lt;interval & gt[& lt;count & gt] ]]5.2.2 options的options值-class:显示关于ClassLoader的信息-compiler:显示关于JIT编译的信息-gc:显示关于gc的信息-gccapacity:显示每代的容量和使用情况-gccause:显示关于垃圾收集的信息(同-gcutil),同时, 显示上次或当前垃圾收集的原因-gcnew:显示新生成信息-gcnewcapacity:显示新生成大小和使用情况-gccold:显示旧龄信息-gcoldcapacity:显示旧龄大小-gcpermpacity:显示永久生成大小-gcutil:显示垃圾收集信息-printcomp Il:输出JIT编译的方法信息-t:在输出信息前添加时间戳列以显示程序的运行时间-h:周期性数据输出后可以输出多少行数据, 后跟一个头信息间隔:用于指定输出统计数据的周期,单位为毫秒计数:用于指定一个数据输出多少次。 5.2.3示例1显示了GC相关信息。

jstat -gc 7063 500 47063 是进程ID ,采样时间间隔为500ms,采样数为4

03.png

S0C:年轻一代第一幸存者的容量(字节)S1C:年轻一代第二幸存者的容量(字节)S0U:年轻一代第一幸存者已使用空(字节)S1U:年轻一代第二幸存者。EC:年轻一代伊甸园的容量(字节)EU:年轻一代伊甸园之前空的容量(字节)OC:老一代的容量(字节)OU:老一代已经使用空(字节)MC: metaspace(元/[ 0/])当前使用空(字节)CCSC:压缩类空大小CCSU:压缩类空使用大小Ygc:年轻一代从应用启动到采样的gc数量YGCT:时间 年轻一代从应用程序启动到采样所用的Gc时间FgcT:老一代(完整GC)从应用程序启动到采样所用的时间GCT:GC从应用程序启动到采样所用的总时间示例2显示了有关垃圾收集的信息。

jstat -gcutil 7737 5s 5

04.png

年轻一代中第一个幸存者使用的当前容量百分比S0 S1年轻一代中第二个幸存者使用的当前容量百分比E年轻一代中Eden使用的当前容量百分比O老一代使用的当前容量百分比M Metaspace使用的当前容量百分比CCS压缩使用率YGC Gc年轻一代中从应用程序启动到采样的时间YgcT从应用程序启动到采样的时间(秒)Fgc 从应用启动到采样老一代的时间(full gc)gc乘以FGCT从应用启动到采样老一代的时间(full gc)gc Time (s)从应用启动到采样GC (s)的总时间5.3 JinFoJinfo: java配置信息Jinfo可以用来查看正在运行的java程序的扩展参数,甚至支持在运行时修改一些参数。

5.3.1 使用语法

Jinfo[option]& lt;pid & gt5.3.2选项可选值-标志打印指定VM标志的值-flag[+|-]& lt;名称& gt启用或禁用指定的VM标志-flag & lt;名称& gt= & lt值& gt将指定的VM标志设置为给定值-flags打印VM标志-sysprops打印Java系统属性& lt没有选项& gt要打印以上两项-h |-help打印此帮助消息5.3.2示例1检查最大堆值。

~ j info-flag最大堆大小8384-xx: max heap size = 10485760示例2查看所有参数

~ Jinfo-flags 8384正在附加到进程ID 8384,请稍候…调试器已成功附加。检测到服务器编译器。JVM版本是25.121-B13非默认VM标志:-XX:CICompilerCount = 4-XX:Initial heap size = 10485760-XX:maxheap size = 10485760-XX:MaxNewSize = 3145728-XX:minheapdetabytes = 524288-XX:NewSize = 3145728-XX:OldSize = 7340032-XX:+use compress edcs pointers-XXENCODING = UTF-8示例3查看使用的垃圾收集器

~ JIINFO-flauseparallelgc 8384-xx:+useparallelgc ~ JIINFO-flauseconmarksweepgc 8384-xx:-useconmarksweepgce示例4设置日志打印

~ Jinfo-flag printcdetails 8384-XX:-printcdetails ~ Jinfo-flag+printcdetails 8384 ~ Jinfo-flag printcdetails 8384-XX:+printcdetails ~ Jinfo-flag-printcdetails 8384 ~ j info-flag printcdetails 8384-XX:-printcdetails 5.4 jmap jmap:内存映射jmap可以查看堆内存使用情况,一般与jhat配合使用。

5.4.1 使用语法

jmap[选项]& lt;pid & gt(连接到正在运行的进程)jmap[option]& lt;可执行文件& ltcore & gt(连接到核心文件)jmap[option][server _ id @]& lt;远程服务器IP或主机名& gt(连接到远程调试服务器)选项:选项参数。Pid:需要打印其配置信息的进程id。可执行文件:生成核心转储的Java可执行文件。Core:需要打印配置信息的核心文件。Server-id:可选的唯一id。如果多个调试服务器在同一远程主机上运行,请使用此选项参数来标识服务器。远程IP或主机名:远程调试服务器的IP地址或主机名。

5.4.2 option可选值

& lt无& gt要打印与Solaris pmap-heap相同的信息,请打印java堆摘要-histo[:live]以打印java对象堆的直方图;如果& # 34;直播& # 34;子选项,只计算活动对象-clstats打印类加载器统计信息-finalizerinfo打印等待终结的对象的信息-dump:& lt;转储选项& gt转储hprof二进制格式的java堆。与-dump一起使用:& lt转储选项& gt& ltpid & gt或-histo在& ltpid & gt没有反应。& # 34;直播& # 34;此模式不支持子选项。-h |-帮助打印此帮助消息-J & lt;flag & gt通过& ltflag & gt直接到运行时系统没有选项:查看进程的内存映像信息,类似于Solaris pmap命令。heap:Show Java heap details histo[:live]:显示堆中对象的统计信息clstats:Print class loader information finalizer info:显示F-Queue队列中等待终结器线程执行终结器方法dump::生成堆转储快照F:当-dump没有响应时,使用-dump或-histo参数。在此模式下,live子参数无效。help:打印帮助信息j:指定传递给运行jmap的JVM的参数。

dump-options可选值

-仅实时转储实时对象;如果未指定,则转储堆中的所有对象。-format=b二进制格式-file = & lt;文件& gt将堆转储到& lt文件& gt示例:jmap -dump:live,format=b,file = heap.bin & ltpid & gt5.4.3示例1显示了Java堆的详细信息

Jmap -heap pid打印堆的摘要信息,包括使用的GC算法、堆配置信息和每个内存区域的内存使用信息。

~ jmap-heap 8985正在附加到进程ID 8985,请稍候…调试器已成功附加。检测到服务器编译器。JVM版本是25.121-B13,使用线程本地对象分配。具有8个线程的并行GC堆配置:minheafpreeratio = 0 maxheapfreeratio = 100 maxheapsize = 524288000(500.0 MB)new size = 174587904(166.5 MB)max new size = 174587904(166.5 MB)OldSize = 349700096(333.5 MB)new ratio = 2 survivorratio = 8 metaspace size = 21800示例2显示了堆中对象的统计信息。

Jmap -histo:包含每个Java类、对象数量、内存大小(单位:字节)和完全限定类名的live pid。虚拟机中打印的类名将以“*”为前缀。如果指定了live子选项,则只计算活动对象。

~ jmap-histo:live 8985 num # instances # bytes类名-1:3682 339156840[B 2:3806 408160[C 3:3794 91056 Java . lang . string 4:593 67480 Java . lang . class 5:587 54568[ljava . lang . object;6:327352368 com . kkb . Example . heapstancestest示例3打印类装入器信息

Jmap -clstats pid-clstats是-permstat的替代选项。在JDK8之前,-permstat用于打印类加载器的数据来打印类加载器在Java堆内存持久存储区的智能统计。对于每个类装入器,它的名称、活动、地址、父类装入器、装入的类的数量和大小都将被打印出来。此外,还将打印包含的字符串的数量和大小。

~ jmap-clstats 8985正在附加到进程ID 8985,请稍候…调试器已成功附加。检测到服务器编译器。JVM版本是25.121-B13查找类加载器实例..完成。按负载统计计算..完成。请稍候..计算能力………………………………………………………………………………………done.class_loader类字节parent_loader alive?type & ltbootstrap & gt517 969116 null live & lt内部& gt0x 00000007 af 095 a08 0 0x 00000007 AE 86 f 288 live Java/util/resource bundle $ Rb class loader @ 0x 00000007 c 00555 e 80000007 AE 86 f 288 9 29861 0x 000000007 AE 8770 F8 live sun/misc/Launcher $ app class loader @ 0x 00000007 c 000 f 6 a 000007 AE 8770 f 8000 null

jmap-finalize rinfo PID ~ jmap-finalize rinfo 10067正在附加到进程ID 10067,请稍候…调试器已成功附加。检测到服务器编译器。JVM版本为25.121-B13等待终结的对象数:0等待终结的对象数:0表示当前F-QUEUE队列中没有等待Fializer线程的最终执行。

示例五

生成堆转储快照转储文件

Jmap-dump: format = b,file = heapdump.dumppid以hprof二进制格式将Java堆转储到具有指定文件名的文件中。live子选项是可选的。如果指定了live子选项,则只会转储堆中的活动对象。要浏览堆转储,可以使用jhat(Java heap analyzer)来读取生成的文件。

当执行这个命令时,JVM会将整个堆的信息转储写入一个文件。如果堆很大,这个过程会很耗时。在执行过程中,为了保证转储信息的可靠性,应用程序会被挂起,因此应谨慎使用在线系统。

~ jmap -dump:format=b,file=heapdump.dump 10067将堆转储到/Users/hadoop/heapdump.dump…5.5 jhatjhat:Java堆分析工具

Jhat命令解析Java堆转储文件并启动web服务器,然后使用浏览器从转储中查看和浏览堆。

Jhat命令支持预先设计的查询,比如显示一个类的所有实例。它还支持对象查询语言(OQL)。OQL有点像SQL,专门用于查询堆转储。

5.5.1 使用语法

jhat[options]heap-dump-file 5 . 5 . 2 options可选值-stack false|true关闭跟踪对象分配调用堆栈。如果堆转储中没有分配位置信息,则必须将该标志设置为false。默认值为true。-refs false|true关闭对对象引用的跟踪。默认值为true。默认情况下,返回的指针是一个指向其他特定对象的对象,如referrers或传入引用,堆中的所有对象都将被计数和计算。-port port-number设置jhat HTTP服务器的端口号。默认值为7000。-exclude exclude-file指定列出应从可访问对象查询中排除的数据成员的文件。例如,如果在文件列中列出了java.lang.String.value,则在计算从特定对象Object o可达对象的列表时,引用路径涉及java.lang.String.value的对象将被排除在外。-baseline exclude-file指定基线堆转储。在两个堆转储中具有相同对象ID的对象将被标记为不是新的,而其他对象将被标记为新的。在比较两个不同的堆转储时很有用。-debug int设置调试级别。0表示不输出调试信息。该值越大,输出的调试信息就越详细。-version启动,仅显示版本信息并退出-h显示帮助信息并退出。用-help-help显示帮助信息并退出。与-h-j相同

05.png

这样就启动了一个简单的HTTP服务,端口号为7000。尝试用浏览器访问它。本地的可以通过http://localhost:7000:

jhat启动后显示的html页面中包含有:All classes including platform:显示出堆中所包含的所有的类Show all members of the rootset :从根集能引用到的对象Show instance counts for all classes (including platform/excluding platform):显示平台包括的所有类的实例数量Show heap histogram:堆实例的分布表Show finalizer summary:Finalizer 摘要Execute Object Query Language (OQL) query:执行对象查询语句(OQL)

从[I a where a.length >中选择一个26//查询长度大于256的数组。5.6 jstackjstack:Java堆栈跟踪

Jstack是java虚拟机自带的堆栈跟踪工具。Jstack用于生成java虚拟机当前时刻的线程快照。线程快照是当前java虚拟机中每个线程正在执行的方法堆栈的集合。生成线程快照的主要目的是定位线程长期停滞的原因,如线程间死锁、无限循环、请求外部资源导致的长时间等待等。当一个线程停止时,通过jstack查看每个线程的调用栈,就可以知道没有响应的线程在后台做什么或者在等待什么资源。

如果一个java程序崩溃生成了一个核心文件,那么可以使用jstack工具获取核心文件的java栈和native栈的信息,这样你就可以很容易的知道java程序是怎么崩溃的,问题出在程序的什么地方。另外,jstack工具可以附加在正在运行的java程序上,你可以看到当时正在运行的java程序的java栈和native栈的信息。如果正在运行的Java程序处于挂起状态,jstack就非常有用。

5.6.1 使用语法

Jstack [option] pid查看当前时间点,指定进程的转储栈信息。jstack[option]PID & gt;将文件当前时间点的指定进程的转储堆栈信息写入指定文件。注意:如果文件不存在,会自动生成;如果文件存在,它将覆盖源文件。Jstack [option]可执行核心查看核心文件在当前时间点的转储堆栈信息。jstack[option][server _ id @]& lt;远程服务器IP或主机名& gt检查远程机器在当前时间点的转储堆栈信息。5.6.2选项可选值-F强制jstack。当进程挂起时,此时& # 39;jstack[-l]PID & # 39;没有回应。此时,该参数可用于强制打印堆栈信息。一般不需要。-m打印java和原生c/c++框架的所有堆栈信息。您可以打印JVM的堆栈,以及Native的堆栈帧,这对于一般的应用程序故障排除是不需要的。-长长的名单。打印锁的附加信息。例如,属于java.util.concurrent的可拥有的同步器列表将使JVM停止更长时间(这可能要糟糕很多倍。比如常见的jstack可能是毫秒和sub-GC,加-l需要将近一秒的时间)。-不推荐使用l。一般不需要使用。-h或-hel在线程转储中打印帮助信息,注意以下状态。

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

06.png

示例2将指定进程的当前堆栈情况记录到一个块中。

07.png

示例3计算线程数量

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gibiH2fE-1660299442837)(https://pics6.baidu.com/feed/203fb80e7bec54e7c75e1edde61b64584ec26a6b.png?token=157827beeb1a3cb378be8639c8d21cae)]【外链图像传输失败,源站可能有防盗链机制。建议保存图片直接上传(IMG-gibi H2 Fe-1660299442837)(https://pics6.baidu.com/feed/203FB80E7BEC54E7C75E1 edde 61 b 64584EC26a6b.png?token = 157827 bee B1 a3 CB 378 be 8639 c8 d 21 CAE)]

08.png

示例4死锁检测

09.png

10.png

5.7 hprof

HPF:堆/CPU分析工具可以显示CPU利用率,并计算堆内存使用量。

J2SE提供了一个简单的命令行工具来分析cpu和java程序堆,称为HPROF。HPROF实际上是JVM中的一个本地库。它将在JVM启动时由命令行参数动态加载,并成为JVM进程的一部分。为了在java进程启动时使用HPROF,用户可以使用HPROF通过各种类型的命令行参数来分析java进程的堆或(和)cpu。HPROF生成的分析数据可以是二进制或文本格式。这些日志可以用来跟踪和分析java进程的性能问题和瓶颈,解决内存使用或程序实现中的问题。JVM中的HAT工具也可以浏览和分析二进制格式的日志,观察java进程堆中的各种类型和数据。在J2SE 5.0之后,HPROF被合并到Java虚拟机工具接口(JVMTI)中。

5.7.1 使用语法

java -agentlib:hprof[=options] ToBeProfiledClassjava -Xrunprof[:options] ToBeProfiledClassjavac -J-agentlib:hprof[=options] ToBeProfiledClass5.7.2 options可选值

Option Name and Value Description Default——————— ———– ——-heap=dump|sites|all heap profiling allcpu=samples|times|old CPU usage offmonitor=y|n monitor contention nformat=a|b text(txt) or binary output afile=<file> write data to file java.hprof[.txt]net=<host>:<port> send data over a socket offdepth=<size> stack trace depth 4interval=<ms> sample interval in ms 10cutoff=<value> output cutoff point 0.0001lineno=y|n line number in traces? ythread=y|n thread in traces? ndoe=y|n dump on exit? ymsa=y|n Solaris micro state accounting nforce=y|n force output to <file> yverbose=y|n print messages about dumps y

11.png

5.7.3 示例官方示例

CPU使用情况采样分析示例(CPU = samples)下面,CPU消耗信息每20毫秒采样一次,堆栈深度为3。生成的概要文件名称是java.hprof.txt,它位于当前目录中。

Java-Agent Lib的一个例子:hprof = CPU = samples,interval = 20,depth = 3 hello CPU使用次数分析(CPU = times)。与CPU使用率采样概要相比,它可以获得更细粒度的CPU消耗信息,可以详细到每个方法的开始和结束。它的实现使用字节码注入技术(BCI)。

Java-j-agentlib示例:hprof = CPU = timeshello.java堆分配分析(heap = sites)

Java-j-agentlib的例子:hprof = heap = sites hello。Java堆转储(heap = dump)可以生成比上述堆分配分析更详细的堆转储信息:

Java-J-agent lib:hprof = Heap = dump Hello.java虽然在JVM启动参数中添加-xrunrof:Heap = sites参数可以生成CPU/Heap概要文件,但是对JVM性能影响很大,所以不建议用于在线服务器环境。统计方法的一个例子是耗时的。

classes java -agentlib:hprof=cpu=times,interval=10 com.kkb.example.HprofTestDumping CPU usage by timing methods … done.

classes vim java.hprof.txt

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PRHQa1ZI-1660299442839)(https://pics0.baidu.com/feed/d52a2834349b033b01845d3e7dedc9dbd439bdf6.png?token=6a4bf5d39d2964bae903bb3ac3ec50c2)]类java -agentlib:hprof=cpu=times,Interval = 10 com . kkb . example . hproftestdumping通过计时方法使用cpu….done.classes vim java.hprof.txt【外链图片传输失败,源站可能有防盗链机制,建议保存图片直接上传(img-prh QA 1 zi-1660299442839)(https://pics0.baidu.com/feed/d52a2834349b033b 01845d3E7DEDC9DBD439BDF6.png?token = 6 a4 BF 5d 39d 2964 BAE 903 bb 3a 3c 50 c 2)]

12.png

示例二

跟踪点类生成的内存百分比

classes java -agentlib:hprof=heap=sites com.kkb.example.HprofTestDumping allocation sites … done.

classes vim java.hprof.txt

13.png

5.8 jconsole

JConsole:Java Monitoring and Management Console,由Java 5引入,是一个内置的Java性能分析器,可以从命令行或GUI shell中运行。您可以很容易地使用JConsole来监控Java应用程序的性能和跟踪Java代码。

5.8.1 如何启动JConsole

如果它是从命令行启动的,在PATH上创建JDK,然后运行jconsole。如果从GUI shell启动,找到JDK安装路径,打开bin文件夹,双击jconsole。

当分析工具弹出时(取决于运行的Java版本和运行的Java程序的数量),可能会出现一个对话框,要求连接一个进程的URL,或者它可能会列出许多不同的本地Java进程(有时包括JConsole进程本身)来连接。如下图所示:双击要分析的流程。

14.png

5.8.2 如何设置JAVA程序运行时可以被JConsolse连接分析

本地程序(相对于打开JConsole的电脑)可以通过本地打开的JConsole连接,不需要设置任何参数(Java SE 6一开始不需要设置,但是之前需要设置运行时参数-Dcom.sun.management.jmxremote)

JConsole如何连接远程机器的JAVA程序?

Jconsole 192.168.0.1:8999也可以在打开的Jconsole界面中运行。连接创建新的连接,选择远程进程,输入远程主机的IP和端口号,点击连接,如下图所示。

15.png

5.8.3 示例

该示例一进入视图就包含这六个标签:

Overview: 显示有关JVM和监视值的概述信息Memory: 显示内存使用信息Threads: 显示线程使用信息Classes: 显示类装载信息VM Summary:显示java VM信息MBeans: 显示 MBeans

16.png

上面的描述有我们需要的信息。同时,右键将数据保存到CSV文件。

内存页签相对于可视化的jstat 命令,用于监视受收集器管理的虚拟机内存。

17.png

6 JVM参数

在JVM调整的过程中,我们主要是调整JVM的参数。这里我们介绍一下主要参数。JVM参数有很多。事实上,我们可以直接使用默认的JVM参数,而不需要修改它们,这可以满足大多数情况。但是,如果想在有限的硬件资源下,最大化部署系统的运行效率,就需要设置相关的JVM参数。

JVM参数主要分为以下三种:标准参数、非标准参数和不稳定参数。

6.1 标准参数

参数,顾名思义,标准参数所包含的函数和输出结果都是非常稳定的,基本不会随着JVM版本的变化而变化。

参数以-开头,如java -version、java -jar等。所有的标准参数都可以通过java -help查询,而且-help也是一个标准参数。

6.2 非标准参数

非标准参数以-X开头,是标准参数的扩展。对应上面提到的标准化参数,这是非标准化参数。意味着在未来的JVM版本中可能会有变化,但这类以-X开头的参数变化较小。我们可以通过Java -X命令检索所有的-X参数。

我们可以通过设置非标准参数来配置堆的内存分配。常用的非标准参数有:

-Xmn新生代内存的大小,包括Eden区和两个Survivor区的总和,写法如:-Xmn1024,-Xmn1024k,-Xmn1024m,-Xmn1g 。-Xms堆内存的最小值,默认值是总内存/64(且小于1G)。默认情况下,当堆中可用内存小于40%(这个值可以用-XX: MinHeapFreeRatio 调整,如-X:MinHeapFreeRatio=30)时,堆内存会开始增加,直增加到-Xmx的大小。-Xmx堆内存的最大值,默认值是总内存/4(且小于1G)。默认情况下,当堆中可用内存大于70%(这个值可以用-XX: MaxHeapFreeRatio调整,如-X:MaxHeapFreeRatio =80)时,堆内存会开始减少,一直减小到-Xms的大小。 * 如果Xms和Xmx都不设置,则两者大小会相同*-Xss每个线程的栈内存,默认1M,般来说是不需要改的。-Xrs减少JVM对操作系统信号的使用。-Xprof跟踪正运行的程序,并将跟踪数据在标准输出输出。适合于开发环境调试。-Xnoclassgc关闭针对class的gc功能。因为其阻至内存回收,所以可能会导致OutOfMemoryError错误,慎用。-Xincgc开启增量gc(默认为关闭)。这有助于减少长时间GC时应用程序出现的停顿,但由于可能和应用程序并发执行,所以会降低CPU对应用的处理能力。-Xloggc:file与-verbose:gc功能类似,只是将每次GC事件的相关情况记录到一个文件中,文件的位置最好在本地,以避免网络的潜在问题。6.3 不稳定参数

这是我们日常开发中最常遇到的参数类型。这也是一个非标准化的参数,相对不稳定,可能会随着JVM版本的变化而变化。它主要用于JVM调优和调试。

不稳定参数以-XX开头,这样的参数设置很容易导致JVM性能的差异,造成JVM的极大不稳定性。如果合理设置这些参数,JVM的性能和稳定性将会得到很大的提高。

不稳定参数分为三类:性能参数:用于JVM的性能调优和内存分配控制,如内存大小的设置行为参数:用于改变JVM的基础行为,如GC的方式和算法的选择调试参数:用于监控、打印、输出jvm的信息不稳定参数语法规则:布尔类型参数值:-XX:+-XX:- 示例:-XX:+UseG1GC,表示启用G1垃圾收集器数字类型参数值: -XX: 示例:-XX:MaxGCPauseMillis=500 ,表示设置GC的最大停顿时间是500ms字符串类型参数值: -XX: 示例:-XX:HeapDumpPath=./dump.core6.4 常参数

–xms4g-xmx4g–xmn 1200m–XSS 512k-xx:new ratio = 4-xx:survivor ratio = 8-xx:maxtenuringthreshold = 15-xx:permsize = 100m-xx:maxperm size = 256m-xx:maxdirectmemorysize =

-Xms4g:初始化堆内存大小为4GB,ms是memory start的简称,等价于-XX:InitialHeapSize。-Xmx4g:堆内存最大值为4GB,mx是memory max的简称,等价于-XX:MaxHeapSize。-Xmn1200m:设置年轻代大小为1200MB。增大年轻代后,将会减小老年代大小。此值对系统性能影响较大, Sun官方推荐配置为整个堆的3/8 。-Xss512k:设置每个线程的堆栈大小。JDK5.0以后每个线程堆栈大小为1MB,以前每个线程堆栈大小为256K。应根据应用线程所需内存大小进行调整。在相同物理内存下,减小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右。-XX:NewRatio=4:设置年轻代(包括Eden和两个Survivor区)与老年代的比值(除去持久代)。设置为4,则年轻代与老年代所占比值为1:4,年轻代占整个堆栈的1/5-XX:SurvivorRatio=8:设置年轻代中Eden区与Survivor区的大小比值。设置为8,则两个Survivor区与个Eden区的比值为2:8,个Survivor区占整个年轻代的1/10-XX:PermSize=100m:初始化永久代大小为100MB。-XX:MaxPermSize=256m:设置持久代大小为256MB。-XX:MaxTenuringThreshold=15:设置垃圾最大年龄。如果设置为0的话,则年轻代对象不经过Survivor区,直接进入老年代。对于老年代比较多的应用,可以提高效率。如果将此值设置为个较大值,则年轻代对象会在Survivor区进行多次复制,这样可以增加对象在年轻代的存活时间,增加在年轻代即被回收的概率。-XX:MaxDirectMemorySize=1G:直接内存。报java.lang.OutOfMemoryError: Direct buffermemory异常可以上调这个值。-XX:+DisableExplicitGC:禁止运行期显式地调用System.gc()来触发fulll GC。 注意: Java RMI的定时GC触发机制可通过配置-Dsun.rmi.dgc.server.gcInterval=86400来控制触发的时间。-XX:CMSInitiatingOccupancyFraction=60:老年代内存回收阈值,默认值为68。-XX:ConcGCThreads=4:CMS垃圾回收器并行线程线,推荐值为CPU核心数。-XX:ParallelGCThreads=8:新生代并行收集器的线程数。-XX:CMSMaxAbortablePrecleanTime=500:当abortable-preclean预清理阶段执行达到这个时间时就会结束。*新生代、老年代、永久代的参数,如果不进性指定,虚拟机会子动选择合适的值,同时也会基于系统的开销自动调整*。6.4.1 -XX:+PrintFlagsInitial、-XX:+PrintFlagsFinal

Java版本6(更新21或21之后),HotSpot JVM提供了两个新参数。JVM启动后,所有XX参数和值都可以在命令行中输出。-XX:+PrintFlagsInitial:检查初始值-XX:+PrintFlagsFinal:检查最终值(初始值可能会修改)。现在让我们知道新参数的输出。-XX:+ PrintFlagsFinal和-client作为参数的结果是一个按字母顺序排列的590个参数的表(注意,每个发布版本的参数数量都不同)

18.png

表格的每一行包括五列,代表一个XX参数。第一列指示参数的数据类型,第二列是名称,第四列是值,第五列是参数的类别。第三列“=”表示第四列是该参数的默认值,而“:=”表示该参数已经由用户或JVM指定。

如果我们只想查看所有XX参数的默认值,可以使用一个相关的参数,- XX:+PrintFlagsInitial。使用- XX:+PrintFlagsInitial,只显示第三列中带有“=”的数据(包括那些设置了其他值的参数)。

但是注意,与-XX:+printlagsfinal比较时,会丢失一些参数,可能是因为这些参数是动态创建的。

19.png

6.4.2 -XX:+PrintCommandLineFlags

我们来看看这个参数。其实这个参数很有用:-XX:+PrintCommandLineFlags。该参数允许JVM打印出由用户或JVM设置的详细XX参数的名称和值。

换句话说,它在第三列中列出了-XX:+PrintFlagsFinal的结果& # 34;:=”的参数。这样,我们可以使用-XX:+PrintCommandLineFlags作为快捷方式来查看修改后的参数。看下面这个例子。

20.png

现在,如果我们在每次启动java程序时设置-XX:+PrintCommandLineFlags,并将其输出到日志文件中,这将记录我们设置的JVM参数对应用程序性能的影响。

6.4.3 GC日志相关

设置JVM GC格式日志的主要参数包括以下八个:

-XX:+PrintGC 输出简要GC日志-XX:+PrintGCDetails 输出详细GC日志-Xloggc:gc.log 输出GC日志到文件-XX:+PrintGCTimeStamps 输出GC的时间戳(以JVM启动到当期的总时长的时间戳形式)-XX:+PrintGCDateStamps 输出GC的时间戳(以日期的形式,如 2020-04-26T21:53:59.234+0800)-XX:+PrintHeapAtGC 在进行GC的前后打印出堆的信息-verbose:gc : 在JDK 8中,-verbose:gc是-XX:+PrintGC一个别称,日志格式等价于:-XX:+PrintGC。不过在JDK 9中 -XX:+PrintGC被标记为deprecated。 -verbose:gc是一个标准的选项,-XX:+PrintGC是一个实验的选项,建议使用-verbose:gc 替代-XX:+PrintGC-XX:+PrintReferenceGC 打印年轻代各个引用的数量以及时长

打开gc日志的方法有很多种,包括:使用两个标志中的任意一个-verbose:gc或者-XX:+PrintGC都可以创建一个基本的GC日志(这两个日志标志实际上是别名,默认情况下GC log功能是关闭的)。使用-xx:+print details标志将创建一个更详细的GC日志。建议使用-XX:+PrintGCDetails标志(默认情况下该标志也是关闭的);通常,使用基本的GC日志很难诊断垃圾收集中的问题。

除了使用详细的GC日志,我们还建议使用-XX:+printgcstimestamps或-XX:+printgcsdatestmps,这样可以更准确地判断几次GC操作之间的时间。这两个参数的区别在于,时间戳是相对于0的值(根据JVM启动的时间),而日期戳是实际的日期字符串。因为日期戳需要渐进式格式化,所以效率可能会稍受影响,但这个操作并不频繁,其影响很难被我们感知。

指定GC日志的路径。默认情况下,GC日志直接输出到标准输出,但是您也可以使用-Xloggc:filename标志将输出修改为文件。除了显式使用-PrintGCDetails标志之外,使用-Xloggc将自动打开基本日志模式。

日志轮换标志可用于限制GC日志中存储的数据量;对于需要长时间运行的服务器来说,这是一个非常有用的标志,否则几个月的数据积累很可能会耗尽服务器的磁盘。

打开日志滚动输出。您可以通过-xx:+usegclogfilerotion-xx:numberofgclogfiles = n-xx:gclogfilesize = n标志来控制日志文件的循环。默认情况下,UseGCLogfileRotation标志是关闭的。它负责打开或关闭GC日志的滚动功能。需要设置-Xloggc参数。在UseGCLogfileRotation标志打开后,默认文件数为0(表示没有限制),默认日志文件大小为0(也没有限制)。因此,为了让日志轮转功能真正生效,我们必须为所有这些标志设置值。

请注意:

设置滚动日志文件的大小,必须大于8k。当前写日志文件大小超过该参数值时,日志将写入下一个文件设置滚动日志文件的个数,必须大于等于1必须设置 -Xloggc 参数开启语句

-XX:+PrintgcDetails-XX:+PrintGCDateStamps-Xloggc:/home/Hadoop/GC . log-XX:+usegclogfileroutation-XX:numberofgclogfilesize = 10-XX:gclogfilesize = 512k其他有用参数-XX:+printgapplicationstoppedtime GC导致的应用程序暂停的打印时间-XX:+printenuringdistribution输出新一代年轻GC每次存活区域内对象的年龄分布。

日志含义

21.png

22.png

6.4.4 -XX:CMSFullGCsBeforeCompaction

CMSFullGCsBeforeCompaction是指在最后一次CMS并发GC执行之后,在压缩之前还要执行多少次完全GC?默认值为0,即在默认配置下,每次CMS GC失败需要切换到全GC时,都会进行压缩。如果将CMSFullGCsBeforeCompaction配置为10,那么上面提到的第一个条件将是真正的全GC每10次压缩一次(而不是CMS并发GC的每10次压缩,目前VM中没有这个参数)。这将使完整的GC压缩得更少,也更容易使旧版本的CMS遭受碎片化。最初,该参数用于配置减少全GC压缩的频率,以减少一些全GC的暂停时间。CMS用于回滚到完整GC的算法是标记-清除-压缩,但是压缩是可选的。不做的话碎片会更严重,但是这次全GC的暂停时间会更短。这是一个权衡。

-xx:+usecmscompactfullcollection-xx:cmsfullgcsbeforeparaction = 10必须同时使用两个参数才能生效。

6.4.5 -XX:HeapDumpPath

堆内存中OOM的概率是所有内存耗尽异常中最高的,错误发生时的堆内信息对解决问题很有帮助,所以设置这个参数(-xx:+heapdumpoutofmemoryerror)让JVM在遇到OOM异常时输出堆内信息,通过(-XX:+HeapDumpPath)参数设置堆内存溢出的快照输出的文件地址,对于相隔几个月发生的OOO特别有用。这两个参数通常一起使用:

-XX:+heapdumponotofmemoryerror-XX:HeapDumpPath =。/6 . 4 . 6-XX:OnOutOfMemoryError-XX:OnOutOfMemoryError = & # 34;/Library/Java/JavaVirtualMachines/JDK 1 . 8 . 0 _ 121 . JDK/Contents/Home/binjconsole & # 34;表示OOM发生后,jconsole程序运行。这里不需要添加” “,因为jconsole.exe路径程序文件包含空。

有了这个参数,我们就可以在系统OOM后自定义一个脚本,用来发送邮件警告信息,重启系统等等。

6.4.7 XX:InitialCodeCacheSize

JVM中一个有趣但经常被忽略的内存区域是“代码缓存”,用于存储编译方法生成的本地代码。诚然,代码缓存很少导致性能问题,但是一旦发生,其影响可能是毁灭性的。如果代码缓存已满,JVM将打印出一条警告消息,并切换到只解释模式:JIT编译器被禁用,字节码将不再被编译成机器码。所以应用会继续运行,只是运行速度会降低一个数量级,直到有人注意到这个问题。

就像其他内存区域一样,我们可以自定义代码缓存的大小。相关的参数是-XX:InitialCodeCacheSize和-XX:ReservedCodeCacheSize,它们的参数是字节值,如上所述。

6.4.8 -XX:+UseCodeCacheFlushing

如果代码缓存不断增长,例如,由于热部署导致的内存泄漏,增加代码的缓存大小只会延迟其溢出。

为了避免这种情况,我们可以尝试一个有趣的新参数:让JVM在代码缓存满的时候放弃一些编译好的代码。通过使用参数-XX:+UseCodeCacheFlushing,我们至少可以避免JVM在代码缓存已满时切换到仅解释模式。

不过我还是建议尽快解决代码缓存问题的根源,比如找出内存泄露并修复。

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。
本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://51itzy.com/22523.html
(0)
上一篇 2022年 11月 24日 07:31
下一篇 2022年 11月 24日 07:51

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注