• 为什么写博客,是因为遇到的坑,不希望别人在踩一遍!
  • 选择了,剩下的就是坚持和努力-------致自己!
  • 当能力达不到梦想时,更需要学习,努力,拼搏

JVM调优-参数篇

Linux运维 雪豹 2个月前 (07-24) 124次浏览 0个评论

1. 什么是JVM?

JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。Java虚拟机包括一套字节码指令集、一组寄存器、一个栈、一个垃圾回收堆和一个存储方法域。 JVM屏蔽了与具体操作系统平台相关的信息,使Java程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。JVM在执行字节码时,实际上最终还是把字节码解释成具体平台上的机器指令执行。

Java语言的一个非常重要的特点就是与平台的无关性。而使用Java虚拟机是实现这一特点的关键。一般的高级语言如果要在不同的平台上运行,至少需要编译成不同的目标代码。而引入Java语言虚拟机后,Java语言在不同平台上运行时不需要重新编译。Java语言使用Java虚拟机屏蔽了与具体平台相关的信息,使得Java语言编译程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。Java虚拟机在执行字节码时,把字节码解释成具体平台上的机器指令执行。这就是Java的能够“一次编译,到处运行”的原因。

2. JRE/JDK/JVM是什么关系?

JRE(JavaRuntimeEnvironment,Java运行环境),也就是Java平台。所有的Java 程序都要在JRE下才能运行。普通用户只需要运行已开发好的java程序,安装JRE即可。

JDK(Java Development Kit)是程序开发者用来来编译、调试java程序用的开发工具包。JDK的工具也是Java程序,也需要JRE才能运行。为了保持JDK的独立性和完整性,在JDK的安装过程中,JRE也是 安装的一部分。所以,在JDK的安装目录下有一个名为jre的目录,用于存放JRE文件。

JVM(JavaVirtualMachine,Java虚拟机)是JRE的一部分。它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。JVM有自己完善的硬件架构,如处理器、堆栈、寄存器等,还具有相应的指令系统。Java语言最重要的特点就是跨平台运行。使用JVM就是为了支持与操作系统无关,实现跨平台。

3. JVM原理

JVM是java的核心和基础,在java编译器和os平台之间的虚拟处理器。它是一种利用软件方法实现的抽象的计算机基于下层的操作系统和硬件平台,可以在上面执行java的字节码程序。

java编译器只要面向JVM,生成JVM能理解的代码或字节码文件。Java源文件经编译成字节码程序,通过JVM将每一条指令翻译成不同平台机器码,通过特定平台运行。

4. JVM执行程序的过程

1) 加载.class文件 2) 管理并分配内存 3) 执行垃圾收集

JRE(java运行时环境)由JVM构造的java程序的运行环,也是Java程序运行的环境,但是他同时一个操作系统的一个应用程序一个进程,因此他也有他自己的运行的生命周期,也有自己的代码和数据空间。JVM在整个jdk中处于最底层,负责于操作系统的交互,用来屏蔽操作系统环境,提供一个完整的Java运行环境,因此也就虚拟计算机。操作系统装入JVM是通过jdk中Java.exe来完成,通过下面4步来完成JVM环境:1) 创建JVM装载环境和配置 2) 装载JVM.dll 3) 初始化JVM.dll并挂界到JNIENV(JNI调用接口)实例4) 调用JNIEnv实例装载并处理class类。

 

5. JVM的生命周期

1) JVM实例对应了一个独立运行的java程序它是进程级别
a) 启动。启动一个Java程序时,一个JVM实例就产生了,任何一个拥有public static void
main(String[] args)函数的class都可以作为JVM实例运行的起点
b) 运行。main()作为该程序初始线程的起点,任何其他线程均由该线程启动。JVM内部有两种线程:守护线程和非守护线程,main()属于非守护线程,守护线程通常由JVM自己使用,java程序也可以表明自己创建的线程是守护线程
c) 消亡。当程序中的所有非守护线程都终止时,JVM才退出;若安全管理器允许,程序也可以使用Runtime类或者System.exit()来退出

 

2) JVM执行引擎实例则对应了属于用户运行程序的线程它是线程级别的

1.1 Jvm的运行参数

三种类型

  • 标准类型 -help -version
  • -X参数(非标准参数)
    -Xint

-Xcomp

  • -XX参数(使用率较高)

-XX:newSize

-XX:+UseSerialGC

 

-help,-version,-D参数

1.1.1 标准参数

jvm的标准参数,一般都是很稳定的,在未来的JVM版本中不会改变,可以使用java -help 检索出所有的标准参数。 通过以下命令查看:

1.1.1.1 java -help

[root@java-6659567f75-56cdv jar]# java -help

用法: java [-options] class [args…]

(执行类)

或  java [-options] -jar jarfile [args…]

(执行 jar 文件)

其中选项包括:

-d32          使用 32 位数据模型 (如果可用)

-d64          使用 64 位数据模型 (如果可用)

-server       选择 “server” VM

默认 VM 是 server,

因为您是在服务器类计算机上运行。

 

 

-cp <目录和 zip/jar 文件的类搜索路径>

-classpath <目录和 zip/jar 文件的类搜索路径>

用 : 分隔的目录, JAR 档案

和 ZIP 档案列表, 用于搜索类文件。

-D<名称>=<值>

设置系统属性

-verbose:[class|gc|jni]

启用详细输出

-version      输出产品版本并退出

-version:<值>

警告: 此功能已过时, 将在

未来发行版中删除。

需要指定的版本才能运行

-showversion  输出产品版本并继续

-jre-restrict-search | -no-jre-restrict-search

警告: 此功能已过时, 将在

未来发行版中删除。

在版本搜索中包括/排除用户专用 JRE

-? -help      输出此帮助消息

-X            输出非标准选项的帮助

-ea[:<packagename>…|:<classname>]

-enableassertions[:<packagename>…|:<classname>]

按指定的粒度启用断言

-da[:<packagename>…|:<classname>]

-disableassertions[:<packagename>…|:<classname>]

禁用具有指定粒度的断言

-esa | -enablesystemassertions

启用系统断言

-dsa | -disablesystemassertions

禁用系统断言

-agentlib:<libname>[=<选项>]

加载本机代理库 <libname>, 例如 -agentlib:hprof

另请参阅 -agentlib:jdwp=help 和 -agentlib:hprof=help

-agentpath:<pathname>[=<选项>]

按完整路径名加载本机代理库

-javaagent:<jarpath>[=<选项>]

加载 Java 编程语言代理, 请参阅 java.lang.instrument

-splash:<imagepath>

使用指定的图像显示启动屏幕

有关详细信息, 请参阅 http://www.oracle.com/technetwork/java/javase/documentation/index.html

1.1.1.2 java -version

[root@java-6659567f75-56cdv jar]# java -version

java version “1.8.0_60”

Java(TM) SE Runtime Environment (build 1.8.0_60-b27)

Java HotSpot(TM) 64-Bit Server VM (build 25.60-b23, mixed mode)

 

1.1.1.3 -server,-client参数

可以通过-server或-client设置jvm的运行参数。 它们的区别是:

Server VM的初始堆空间会大一些,默认使用的是并行垃圾回收器,启动慢运行快。

Client VM相对来讲会保守一些,初始堆空间会小一些,使用串行的垃圾回收器,它 的目标是为了让JVM的启动速度更快,但运行速度会比Serverm模式慢些。

JVM在启动的时候会根据硬件和操作系统自动选择使用Server还是Client类型的 JVM。

32位操作系统:

如果是Windows系统,不论硬件配置如何,都默认使用Client类型的JVM。

如果是其他操作系统上,机器配置有2GB以上的内存同时有2个以上CPU的话默 认使用server模式,否则使用client模式。

64位操作系统

只有server类型,不支持client类型。

1.2 -X参数(非标准参数)

jvm的-X参数是非标准参数,在不同版本的jvm中,参数可能会有所不同,可以通过java -X查看非标准参数。

 

[root@java-6659567f75-56cdv jar]# java -X

-Xmixed           混合模式执行 (默认)

-Xint             仅解释模式执行

-Xbootclasspath:<用 : 分隔的目录和 zip/jar 文件>

设置搜索路径以引导类和资源

-Xbootclasspath/a:<用 : 分隔的目录和 zip/jar 文件>

附加在引导类路径末尾

-Xbootclasspath/p:<用 : 分隔的目录和 zip/jar 文件>

置于引导类路径之前

-Xdiag            显示附加诊断消息

-Xnoclassgc       禁用类垃圾收集

-Xincgc           启用增量垃圾收集

-Xloggc:<file>    将 GC 状态记录在文件中 (带时间戳)

-Xbatch           禁用后台编译

-Xms<size>        设置初始 Java 堆大小

-Xmx<size>        设置最大 Java 堆大小

-Xss<size>        设置 Java 线程堆栈大小

-Xprof            输出 cpu 配置文件数据

-Xfuture          启用最严格的检查, 预期将来的默认值

-Xrs              减少 Java/VM 对操作系统信号的使用 (请参阅文档)

-Xcheck:jni       对 JNI 函数执行其他检查

-Xshare:off       不尝试使用共享类数据

-Xshare:auto      在可能的情况下使用共享类数据 (默认)

-Xshare:on        要求使用共享类数据, 否则将失败。

-XshowSettings    显示所有设置并继续

-XshowSettings:all

显示所有设置并继续

-XshowSettings:vm 显示所有与 vm 相关的设置并继续

-XshowSettings:properties

显示所有属性设置并继续

-XshowSettings:locale

显示所有与区域设置相关的设置并继续

 

-X 选项是非标准选项, 如有更改, 恕不另行通知。

-Xint、-Xcomp、-Xmixed

 

在解释模式(interpreted mode)下,-Xint标记会强制JVM执行所有的字节码,当然这 会降低运行速度,通常低10倍或更多。

-Xcomp参数与它(-Xint)正好相反,JVM在第一次使用时会把所有的字节码编译成 本地代码,从而带来最大程度的优化。 然而,很多应用在使用-Xcomp也会有一些性能损失,当然这比使用-Xint损失的 少,原因是-xcomp没有让JVM启用JIT编译器的全部功能。JIT编译器可以对是否 需要编译做判断,如果所有代码都进行编译的话,对于一些只执行一次的代码就 没有意义了。

-Xmixed是混合模式,将解释模式与编译模式进行混合使用,由jvm自己决定,这是 jvm默认的模式,也是推荐使用的模式。

 

1.3 -XX参数(使用率较高)

-XX参数也是非标准参数,主要用于jvm的调优和debug操作。

 

-XX参数的使用有2种方式,一种是boolean类型,一种是非boolean类型:

 

1.3.1.1 boolean类型

格式:-XX:[±]

如:-XX:+DisableExplicitGC 表示禁用手动调用gc操作,也就是说调用 System.gc()无效

非boolean类型

格式:-XX:

如:-XX:NewRatio=1 表示新生代和老年代的比值

 

1.3.2 -Xms与-Xmx参数

-Xms与-Xmx分别是设置jvm的堆内存的初始大小和最大大小。

-Xmx2048m:等价于-XX:MaxHeapSize,设置JVM最大堆内存为2048M。

-Xms512m:等价于-XX:InitialHeapSize,设置JVM初始堆内存为512M。 适当的调整jvm的内存大小,可以充分利用服务器资源,让程序跑的更快。

示例:

1.3.3 查看jvm的运行参数

有些时候我们需要查看jvm的运行参数,这个需求可能会存在2种情况:

第一,运行java命令时打印出运行参数;

运行java命令时打印参数,需要添加-XX:+PrintFlagsFinal参数即可。

[root@java-6659567f75-56cdv jar]# java -XX:+PrintFlagsFinal

由上述的信息可以看出,参数有boolean类型和数字类型,值的操作符是=或:=,分别代 表默认值和被修改的值。

images1.3.3.1 查看正在运行的java进程的参数;

如果想要查看正在运行的jvm就需要借助于jinfo命令查看。

[root@java-6659567f75-56cdv jar]# jinfo -flags 6

Attaching to process ID 6, please wait…

Debugger attached successfully.

Server compiler detected.  # Server 编译器

JVM version is 25.60-b23

# 非标准的

Non-default VM flags: -XX:CICompilerCount=15 -XX:ConcGCThreads=6 -XX:G1HeapRegionSize=1048576 -XX:InitialHeapSize=1048576000 -XX:MarkStackSize=4194304 -XX:MaxHeapSize=1048576000 -XX:MaxNewSize=268435456 -XX:MinHeapDeltaBytes=1048576 -XX:NewSize=67108864 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps -XX:+UseG1GC

#

Command line:  -Xmx1000m -Xms1000m -Xmn256m -XX:PermSize=128m -XX:MaxPermSize=256m -XX:NewSize=64m -XX:+UseG1GC -Dserver.port=8080 -Dspring.profiles.active=test

 

##这是所有的信息,还可以查看单个信息,查看某一参数的值,用法:jinfo ‐flag <参数名> <进程id>

[root@java-6659567f75-56cdv jar]#  jinfo -flag MaxHeapSize 6

-XX:MaxHeapSize=1048576000

 

 

1.4 jvm内存模型

jvm的内存模型在1.7和1.8有较大的区别,虽然本套课程是以1.8为例进行讲解,但是我们也是需要对1.7的内存模型有所了解,所以接下里,我们将先学习1.7再学习1.8的内存模型。

Jvm 调优较多是内存里面调优,内存使用和回收(其中重要的就是垃圾回收器的算法和内存模型息息相关),垃圾回收算法根据内存分块,分区的对象大小性质不一样。)

垃圾回收算法间隔时间越短,应用影响越短,性能越好,full gc 一直full  gc占用时间长,影响应用性能。

 

1.4.1 1、jdk1.7的堆内存模型

images

  • Young 年轻区(代):

Young区被划分为三部分,Eden区和两个大小严格相同的Survivor区,其中, Survivor区间中,某一时刻只有其中一个是被使用的,另外一个留做垃圾收集时复制 对象用,在Eden区间变满的时候, GC就会将存活的对象移到空闲的Survivor区间 中,根据JVM的策略,在经过几次垃圾收集后,任然存活于Survivor的对象将被移动到Tenured区间。

总结:年轻代包含 eden(翻译:伊甸园) 年轻代使用最频繁,新的new对象如果创建在这里创建,进一步使用,并回收。如果创建的字符串没有引用就会被回收,经过一段时间使用,eden对象会越来越多,如果没有多余的空间名,就会移到S0 Survivor 翻译:幸存者

  • Tenured 年老区:

Tenured(翻译:老年代) 区主要保存生命周期长的对象,一般是一些老的对象,当一些对象在Young 复制转移一定的次数以后,对象就会被转移到Tenured区,一般如果系统中用了 application级别的缓存,缓存中的对象往往会被转移到这一区间。

       总结:如果是一直在年老区,说明对象很难回收 1、要么代码逻辑有问题 2、要么对象使用频繁

              Full gc 一般回收都是在Tenured(翻译:老年代)区

  • Perm 永久区:

Perm代主要保存class,method,filed对象,这部份的空间一般不会溢出,除非一次性 加载了很多的类,不过在涉及到热部署的应用服务器的时候,有时候会遇到 java.lang.OutOfMemoryError : PermGen space 的错误,造成这个错误的很大原因 就有可能是每次都重新部署,但是重新部署后,类的class没有被卸载掉,这样就造 成了大量的class对象保存在了perm中,这种情况下,一般重新启动应用服务器可以 解决问题。

  • Virtual区:

最大内存和初始内存的差值,就是Virtual区。

1.4.2 2、jdk1.8的堆内存模型

images

由上图可以看出,jdk1.8的内存模型是由2部分组成,年轻代 + 年老代。 年轻代:Eden + 2*Survivor 年老代:OldGen 在jdk1.8中变化最大的Perm区,用Metaspace(元数据空间)进行了替换。 需要特别说明的是:Metaspace所占用的内存空间不是在虚拟机内部,而是在本地内存 空间中,这也是与1.7的永久代最大的区别所在 。

1.4.3 3、为什么要废弃1.7中的永久区?

官网给出了解释:http://openjdk.java.net/jeps/122

This is part of the JRockit and Hotspot convergence effort. JRockitcustomers do not need to configure the permanent generation (since JRockitdoes not have a permanent generation) and are accustomed to notconfiguring the permanent generation.移除永久代是为融合HotSpot JVM与 JRockit VM而做出的努力,因为JRockit没有永久代,不需要配置永久代。

现实使用中,由于永久代内存经常不够用或发生内存泄露,报出异常 java.lang.OutOfMemoryError: PermGen 基于此,将永久区废弃,而改用元空间,改为了使用本地内存空间。

总结:因为永久区里面放的是字节码之类的,需要新增Java文件都需要重启,就释放永久区。

1.4.4 4、通过jstat命令查看堆内存使用情况

jstat命令可以查看堆内存各部分的使用量,以及加载类的数量。

命令的格式如下:

jstat [-命令选项] [vmid] [间隔时间/毫秒] [查询次数]

  • 查看class加载数统计

[root@java-6659567f75-56cdv jar]# jps

248866 Jps

6 jar

[root@java-6659567f75-56cdv jar]# jstat -class 6

Loaded  Bytes  Unloaded  Bytes     Time

17421 32198.1      263   292.1      26.14

说明:

Loaded:加载class的数量

Bytes:所占用空间大小

Unloaded:未加载数量

Bytes:未加载占用空间 (KB)单位

Time:时间

  • 查看编译统计

[root@java-6659567f75-56cdv jar]# jstat -compiler 6

Compiled Failed Invalid   Time   FailedType FailedMethod

21829      6       0   249.18          1 org/springframework/core/ResolvableType forTyp

说明: Compiled:编译数量。 Failed:失败数量 Invalid:不可用数量 Time:时间 FailedType:失败类型 FailedMethod:失败的方法

  • 垃圾回收统计

[root@java-6659567f75-56cdv jar]# jstat -gc 6

S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT

0.0   2048.0  0.0   2048.0 67584.0  50176.0   954368.0   342191.4  104396.0 97564.0 12800.0 11467.6   7774   35.025   0      0.000   35.025

说明:

S0C:第一个Survivor区的大小(KB)

S1C:第二个Survivor区的大小(KB)

S0U:第一个Survivor区的使用大小(KB) 已经使用

S1U:第二个Survivor区的使用大小(KB) 已经使用

EC:Eden区的大小(KB)

EU:Eden区的使用大小(KB)

OC:Old区大小(KB)

OU:Old使用大小(KB)

MC:方法区大小(KB)

MU:方法区使用大小(KB)

CCSC:压缩类空间大小(KB)

CCSU:压缩类空间使用大小(KB)

YGC:年轻代垃圾回收次数

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

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

GCT:垃圾回收消耗总时间(YGCT+ FGCT)

root@java-6659567f75-56cdv jar]# jstat -gc 6 1000 5

其中:1000毫秒,只1秒 打印5次

 

1.5 四、jmap的使用以及内存溢出分析

前面通过jstat可以对jvm堆的内存进行统计分析,而jmap可以获取到更加详细的内容。如:内存使用情况的汇总、对内存溢出的定位与分析。

1.5.1 1、查看内存使用情况

[root@java-6659567f75-56cdv jar]# jmap -heap 6

Attaching to process ID 6, please wait…

Debugger attached successfully.

Server compiler detected.

JVM version is 25.60-b23

 

using thread-local object allocation.

Garbage-First (G1) GC with 23 thread(s)

 

Heap Configuration:

MinHeapFreeRatio         = 40

MaxHeapFreeRatio         = 70

MaxHeapSize              = 1048576000 (1000.0MB)

NewSize                  = 67108864 (64.0MB)

MaxNewSize               = 268435456 (256.0MB)

OldSize                  = 5452592 (5.1999969482421875MB)

NewRatio                 = 2

SurvivorRatio            = 8

MetaspaceSize            = 21807104 (20.796875MB)

CompressedClassSpaceSize = 1073741824 (1024.0MB)

MaxMetaspaceSize         = 17592186044415 MB

G1HeapRegionSize         = 1048576 (1.0MB)

 

Heap Usage:

G1 Heap:

regions  = 1000

capacity = 1048576000 (1000.0MB)

used     = 393269952 (375.05145263671875MB)

free     = 655306048 (624.9485473632812MB)

37.50514526367188% used

G1 Young Generation:

Eden Space:

regions  = 39

capacity = 69206016 (66.0MB)

used     = 40894464 (39.0MB)

free     = 28311552 (27.0MB)

59.09090909090909% used

Survivor Space:

regions  = 2

capacity = 2097152 (2.0MB)

used     = 2097152 (2.0MB)

free     = 0 (0.0MB)

100.0% used

G1 Old Generation:

regions  = 335

capacity = 977272832 (932.0MB)

used     = 350278336 (334.05145263671875MB)

free     = 626994496 (597.9485473632812MB)

35.842430540420466% used

 

34411 interned Strings occupying 3636304 bytes.

 

 

Attaching to process ID 3764, please wait…

Debugger attached successfully.

Server compiler detected.

JVM version is 25.171-b11

 

using thread-local object allocation.

Parallel GC with 8 thread(s) //采用Parallel GC

 

Heap Configuration: (堆得配置)

MinHeapFreeRatio         = 0    //JVM最小空闲比率 可由-XX:MinHeapFreeRatio=<n>参数设置, jvm heap 在使用率小于 n 时 ,heap 进行收缩

MaxHeapFreeRatio         = 100  //JVM最大空闲比率 可由-XX:MaxHeapFreeRatio=<n>参数设置, jvm heap 在使用率大于 n 时 ,heap 进行扩张

MaxHeapSize              = 2095054848 (1998.0MB) //JVM堆的最大大小 可由-XX:MaxHeapSize=<n>参数设置

NewSize                  = 44040192 (42.0MB) //JVM新生代的默认大小 可由-XX:NewSize=<n>参数设置

MaxNewSize               = 698351616 (666.0MB) //JVM新生代的最大大小 可由-XX:MaxNewSize=<n>参数设置

OldSize                  = 88080384 (84.0MB) //JVM老生代的默认大小 可由-XX:OldSize=<n>参数设置

NewRatio                 = 2 //新生代:老生代(的大小)=1:2 可由-XX:NewRatio=<n>参数指定New Generation与Old Generation heap size的比例。

SurvivorRatio            = 8 //survivor:eden = 1:8,即survivor space是新生代大小的1/(8+2)[因为有两个survivor区域] 可由-XX:SurvivorRatio=<n>参数设置

MetaspaceSize            = 21807104 (20.796875MB) //元空间的默认大小,超过此值就会触发Full GC 可由-XX:MetaspaceSize=<n>参数设置

CompressedClassSpaceSize = 1073741824 (1024.0MB) //类指针压缩空间的默认大小 可由-XX:CompressedClassSpaceSize=<n>参数设置

MaxMetaspaceSize         = 17592186044415 MB //元空间的最大大小 可由-XX:MaxMetaspaceSize=<n>参数设置

G1HeapRegionSize         = 0 (0.0MB) //使用G1垃圾收集器的时候,堆被分割的大小 可由-XX:G1HeapRegionSize=<n>参数设置

 

Heap Usage:

 

PS Young Generation //新生代区域分配情况

Eden Space: //Eden区域分配情况

capacity = 89653248 (85.5MB)

used     = 8946488 (8.532035827636719MB)

free     = 80706760 (76.96796417236328MB)

9.978989272089729% used  #使用率

From Space: //其中一个Survivor区域分配情况

capacity = 42467328 (40.5MB)

used     = 15497496 (14.779563903808594MB)

free     = 26969832 (25.720436096191406MB)

36.49275037977431% used

To Space:  //另一个Survivor区域分配情况

capacity = 42991616 (41.0MB)

used     = 0 (0.0MB)

free     = 42991616 (41.0MB)

0.0% used

PS Old Generation //老生代区域分配情况

capacity = 154664960 (147.5MB)

used     = 98556712 (93.99100494384766MB)

free     = 56108248 (53.508995056152344MB)

63.722715216167906% used

 

1819 interned Strings occupying 163384 bytes.

Heap Usage:# 堆内存的使用情况G1 Heap:#G1堆情况   regions  = 1024   capacity = 1073741824 (1024.0MB)   used     = 45869552 (43.74461364746094MB)   free     = 1027872272 (980.2553863525391MB)   4.271934926509857% usedG1 Young Generation:#年轻代Eden Space:   regions  = 26   capacity = 79691776 (76.0MB)   used     = 27262976 (26.0MB)   free     = 52428800 (50.0MB)   34.21052631578947% usedSurvivor Space:   regions  = 4   capacity = 4194304 (4.0MB)   used     = 4194304 (4.0MB)   free     = 0 (0.0MB)   100.0% usedG1 Old Generation:##G1老年代   regions  = 14   capacity = 50331648 (48.0MB)   used     = 14412272 (13.744613647460938MB)   free     = 35919376 (34.25538635253906MB)   28.63461176554362% used 16879 interned Strings occupying 1583944 bytes.

1.5.2 2、查看内存中对象数量及大小

[root@java-6659567f75-56cdv jar]# jmap  -histo 6

 

num     #instances         #bytes  class name

———————————————-

1:         80514      127363104  [B

2:         30173      106562080  [I

3:        144651       31577928  [C

4:         78679        7014864  [Ljava.lang.Object;

5:         79917        3836016  java.util.HashMap

6:        141514        3396336  java.lang.String

7:         48927        2739912  java.util.LinkedHashMap

8:         78012        2496384  java.util.concurrent.ConcurrentHashMap$Node

9:         42777        2395512  java.util.stream.ReferencePipeline$Head

10:         59200        2368000  java.util.TreeMap$Entry

11:         91622        2198928  java.util.ArrayList

12:         13343        2139760  [J

13:         18246        2015864  java.lang.Class

14:         30459        1949376  java.util.stream.ReferencePipeline$2

15:         25879        1945312  [Ljava.util.HashMap$Node;

16:         20382        1793616  java.lang.reflect.Method

17:         50177        1605664  java.util.HashMap$Node

18:         37467        1498680  java.util.LinkedHashMap$Entry

19:         46321        1482272  java.util.stream.Collectors$CollectorImpl

20:         35582        1423280  java.util.HashMap$KeyIterator

21:         41774        1336768  java.lang.StackTraceElement

#查看所有对象,包括活跃以及非活跃的jmap ‐histo <pid> | more#查看活跃对象jmap ‐histo:live <pid> | more

#对象说明 B byte C char D double F float I int J long Z boolean [ 数组,如[I表示int[] [L+类名 其他对象

1.5.3 3、将内存使用情况dump到文件中

有些时候我们需要将jvm当前内存中的情况dump到文件中,然后对它进行分析,jmap也是支持dump到文件中的。

#用法: format=b 二进制jmap ‐dump:format=b,file=dumpFileName <pid>[root@java-6659567f75-56cdv jar]# jmap -dump:format=b,file=dump.dat 6Dumping heap to /usr/local/jar/dump.dat …Heap dump file created#示例jmap ‐dump:format=b,file=/root/dump.dat 3694

已经在/root下生成了dump.dat文件

1.5.4 4、jhat对dump文件进行分析

在上一小节中,我们将jvm的内存dump到文件中,这个文件是一个二进制的文件,不方便查看,这时我们可以借助于jhat工具进行查看。

#用法:jhat ‐port <port> <file>#示例:[root@myshop02 ~]# jhat -port 9998 /root/dump.datReading from /root/dump.dat…Dump file created Mon Apr 06 15:10:56 CST 2020Snapshot read, resolving…Resolving 269315 objects…Chasing references, expect 53 dots……………………………………………..Eliminating duplicate references……………………………………………..Snapshot resolved.Started HTTP server on port 9998Server is ready.

打开浏览器进行访问:http://192.168.0.108:9998

如果访问不了,需要防火墙开放9998端口。

[root@myshop02 ~]# firewall-cmd –zone=public –add-port=9998/tcp –permanent;success[root@myshop02 ~]# systemctl restart firewalld.service;

在最后面有OQL查询功能 。

点开之后可以执行OQL查询语句,如下,左侧是查询结果,字符串长度>=100的都查询出来了


致自己: 从2015北漂、2016、2017时间已过去。 2018年从头开始,希望自己珍惜每一秒,每一分钟,选择了剩下的就是坚持和努力,努力吧少年。 雪豹 20180109!
喜欢 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址