jvm命令使用

linux 查看java路径 which java、 whereis java。  echo $JAVA_HOME

设置java环境变量  查看 cat /etc/profile  如果没有设置环境变量可以在 文件最后添加
#set java environment
JAVA_HOME=/usr/java/jdk1.7.0_45
JRE_HOME=$JAVA_HOME/jre
CLASS_PATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib/rt.jar
PATH=$PATH:$JAVA_HOME/bin:$JRE_HOME/bin
export JAVA_HOME JRE_HOME CLASS_PATH PATH

CMS:首先介绍一下新生代、老年代。所谓的新生代和老年代是针对于分代收集算法来定义的,新生代又分为Eden和Survivor两个区。加上老年代就这三个区。数据会首先分配到Eden区 当中(当然也有特殊情况,如果是大对象那么会直接放入到老年代(大对象是指需要大量连续内存空间的java对象),当Eden没有足够空间的时候就会 触发jvm发起一次Minor GC。如果对象经过一次Minor GC还存活,并且又能被Survivor空间接受,那么将被移动到Survivor空 间当中。并将其年龄设为1,对象在Survivor每熬过一次Minor GC,年龄就加1,当年龄达到一定的程度(默认为15)时,就会被晋升到老年代中了,当然晋升老年代的年龄是可以设置的。

G1:G1 垃圾收集器是一种工作在堆内不同分区上的并发收集器。分区(region)既可以归属于 老年代,也可以归属于新生代(默认情况下,一个堆被划分成 2048 个分区),同一个代的分区不需要保持连续。为老年代设计分区的初衷是我们发现并发后台线程在回收老年代中 没有引用的对象时,有的分区垃圾对象的数量很多,另一些分区的垃圾对象相对较少。虽然分区的垃圾收集工作实际仍然会暂停应用程序线程,不过由于 G1 收集器专注于垃圾最 多的分区,最终的效果是花费较少的时间就能回收这些分区的垃圾,这种只专注于垃圾最多分区的方式就是 G1 垃圾收集器名称的由来,即首先收集垃圾最多的分区。

不过这一算法并不适用于新生代的分区:新生代进行垃圾回收时,整个新生代空间要么被回收,要么被晋升(Eden对象被移动到 Survivor 空间,或者移动到老年代)。新生代也采用分区机制的部分原因,是因为采用预定义的分区能够便于代的大小调整。对于 2 GB 的堆, 对象大小如果超过 512 MB 就算大型对象。

G1 收集器最终出现碎片化的堆的频率,跟 CMS 收集器比较起来要小得多的原因——随着 G1 垃圾的回收以这种方式移动对象,实际伴随着压缩。

Java 7Java 8的内存分布图

虚拟机内存与本地内存的区别

Java虚拟机在执行的时候会把管理的内存分配成不同的区域,这些区域被称为虚拟机内存,
同时,对于虚拟机没有直接管理的物理内存,也有一定的利用,这些被利用却不在虚拟机内存数据区的内存,我们称它为本地内存,这两种内存有一定的区别:

JVM内存

  • 受虚拟机内存大小的参数控制,当大小超过参数设置的大小时就会报OOM

本地内存

  • 本地内存不受虚拟机内存参数的限制,只受物理内存容量的限制
  • 虽然不受参数的限制,但是如果内存的占用超出物理内存的大小,同样也会报OOM

永久代和元空间:元空间和永久代都是用来存储class相关信息。方法区只是JVM规范定义,而永久代为具体的实现。从永久代换到元空间的意义在于,PermGen分配多大的空间很难确定,因为PermSize的大小依赖于很多因素,取代后尽可能避免了因为方法区产生的oom。

永久代:受JVM内存大小参数的限制。

元空间:直接放到了本地内存中,不受JVM参数的限制(当然,如果物理内存被占满了,方法区也会报OOM)

 Metaspace 分为两个区域:non-class part 和 class part。

class part:存放 Klass 对象,需要一个连续的不超过 4G 的内存。class part 被称作 Compressed Class Space,这个名字会有点怪,因为 Klass 本身其实没有使用压缩技术,而是引用它们的指针被压缩了
non-class part:包含其他的所有 metadata。

Metaspace 只在 GC 运行并且卸载类加载器的时候才会释放空间。当然,在某些时候,需要主动触发 GC 来回收一些没用的 class metadata,即使这个时候对于堆空间来说,还达不到 GC 的条件。

Metaspace 可能在两种情况下触发 GC:

1、分配空间时:虚拟机维护了一个阈值,如果 Metaspace 的空间大小超过了这个阈值,那么在新的空间分配申请时,虚拟机首先会通过收集可以卸载的类加载器来达到复用空间的目的,而不是扩大 Metaspace 的空间,这个时候会触发 GC。这个阈值会上下调整,和 Metaspace 已经占用的操作系统内存保持一个距离。

2、碰到 Metaspace OOM:Metaspace 的总使用空间达到了 MaxMetaspaceSize 设置的阈值,或者 Compressed Class Space 被使用光了,如果这次 GC 真的通过卸载类加载器腾出了很多的空间,这很好,否则的话,我们会进入一个糟糕的 GC 周期,即使我们有足够的堆内存。

字符串存储: 1.7 及以后版本中,字符串第一次创建时先在堆中被创建,然后会在字符串常量池中创建一个引用指向堆中的对象,所以字符串常量池中保存的都是引用地址。所以通过字符串字面值创建字符串对象时,只要内容一致,内存中只会保留一个对象,常量池中也仅会有一个引用地址。

通过 New String() 方式创建的字符串对象,常量池中并没有保存其引用。不过 String 类提供了一个入池的方法 intern()。通过调用 intern() 方法会先判断常量池中有没值相同的字符串引用,有则直接返回引用地址,没有则复制当前字符串的引用并返回。所以1.7以后字符串都存储在堆中,永久代和元空间只存储引用。

jstat

提供某个进程堆的使用信息,使用 jstat -options 选项能够列出所有这些选项,

l  gcutil (GC统计汇总)
l  class (类加载器) 
l  compiler (JIT) 
l  gc (GC堆状态) 
l  gccapacity (各区大小) 
l  gccause (最近一次GC统计和原因) 
l  gcnew (新区统计)
l  gcnewcapacity (新区大小)
l  gcold (老区统计)
l  gcoldcapacity (老区大小)
l  gcpermcapacity (永久区大小)
l  printcompilation (HotSpot编译统计)

1、-gcutil 

这其中最常用的一个选项是 -gcutil,它能够输出消耗在 GC 上的时间,以及每个 GC 区域使用的百分比。其他的选项能够以 KB 为单位输出各 GC 空间的大小。

注意,jstat 接受一个可选的参数,指定每隔多少毫秒重复执行这个命令,这个选项帮助我们长时间地监控应用程序的垃圾回收过程。下面是一个示例的输出,它以每隔一秒钟的频率运行。

在这个例子中,监控开始时,程序已经在新生代(YGC)中进行了 98 次垃圾回收操作,这总共消耗了大约 1.985 秒的时间(YGCT)。于此同时,它还完成了 8 次 Full GC(FGC),消耗了 2.397 秒的时间(FGCT);因此 GC 消耗的总时长(GCT)为 4.382 秒.

新生代中三个区间的数据都在这里列出:两个 Survivor 空间(分别是 S0 和 S1)以及 1 个Eden 空间(标记为 E)。监控开始时,Eden 空间几乎要被填满了,(已经占用了 99.12% 的 空间),因此下一秒就有一次新生代的垃圾回收:这之后 Eden 空间的使用率回落到 5.55%, Survivor 空间发生了交换,一部分内存对象被晋升到了老年代空间(标记为 O),老年代的 空间使用率增长到 60.98%。跟典型的场景一样,我们没有在永久代(标记为 P)发现大幅 度的变化,因为几乎所有需要的类都已经在程序启动时载入内存。

如果你不记得如何开启 GC 日志,这是一个很好的替代方法,它能帮助我们观察垃圾回收是如何在较长的时间跨度内工作的。

G1 结果:

M:元空间使用率 。CCS:压缩空间使用率

2、jstat –class<pid> : 显示加载class的数量,及所占空间等信息。

 Loaded:装载的类的数量。Bytes:装载类所占用的字节数。Unloaded卸载类的数量

Bytes:卸载类的字节数。Time:装载和卸载类所花费的时间

3、jstat -compiler <pid>显示VM实时编译的数量等信息。

Compiled:编译任务执行数量。Failed:编译任务执行失败数量。Invalid  :编译任务执行失效数量。Time :编译任务消耗时间。FailedType:最后一个编译失败任务的类型。FailedMethod:最后一个编译失败任务所在的类及方法

4、jstat -gc <pid>: 可以显示gc的信息,查看gc的次数,及时间。

 S0C   :年轻代中第一个survivor(幸存区)的容量 (字节)

S1C   :年轻代中第二个survivor(幸存区)的容量 (字节)

S0U  :年轻代中第一个survivor(幸存区)目前已使用空间 (字节)

S1U    :年轻代中第二个survivor(幸存区)目前已使用空间 (字节)

EC     :年轻代中Eden的容量 (字节)

EU     :年轻代中Eden目前已使用空间 (字节)

OC   :Old代的容量 (字节)

OU     :Old代目前已使用空间 (字节)

PC    :Perm(持久代)的容量 (字节)

PU: Perm(持久代)目前已使用空间 (字节)

YGC  :从应用程序启动到采样时年轻代中gc次数

YGCT  :从应用程序启动到采样时年轻代中gc所用时间(s)

FGC   :从应用程序启动到采样时old代(全gc)gc次数

FGCT   :从应用程序启动到采样时old代(全gc)gc所用时间(s)

GCT:从应用程序启动到采样时gc用的总时间(s)

5、jstat -gccapacity <pid>:可以显示,VM内存中三代(young,old,perm)对象的使用和占用大小

 NGCMN   :年轻代(young)中初始化(最小)的大小(字节)

NGCMX   :年轻代(young)的最大容量 (字节)

NGC   :年轻代(young)中当前的容量 (字节)

S0C  :年轻代中第一个survivor(幸存区)的容量 (字节)

S1C     :年轻代中第二个survivor(幸存区)的容量 (字节)

EC     :年轻代中Eden的容量 (字节)

OGCMN   :old代中初始化(最小)的大小 (字节)

OGCMX   :old代的最大容量(字节)

OGC:old代当前新生成的容量 (字节)

OC  :Old代的容量 (字节)

PGCMN   :perm代中初始化(最小)的大小 (字节)

PGCMX   :perm代的最大容量 (字节)  

PGC   :perm代当前新生成的容量 (字节)

PC    :Perm(持久代)的容量 (字节)

YGC   :从应用程序启动到采样时年轻代中gc次数

FGC:从应用程序启动到采样时old代(全gc)gc次数

6、jstat -gcnew <pid>:年轻代对象的信息。

 S0C   :年轻代中第一个survivor(幸存区)的容量 (字节)

S1C   :年轻代中第二个survivor(幸存区)的容量 (字节)

S0U   :年轻代中第一个survivor(幸存区)目前已使用空间 (字节)

S1U  :年轻代中第二个survivor(幸存区)目前已使用空间 (字节)

TT:对象在新生代存活的次数

MTT :对象在新生代存活的最大次数

DSS: survivor区期望的大小

EC     :年轻代中Eden的容量 (字节)

EU    :年轻代中Eden目前已使用空间 (字节)

YGC    :从应用程序启动到采样时年轻代中gc次数

YGCT:从应用程序启动到采样时年轻代中gc所用时间(s)

7、jstat -gcnewcapacity<pid>: 年轻代对象的信息及其占用量。

 NGCMN     年轻代(young)中初始化(最小)的大小(字节)

NGCMX      年轻代(young)的最大容量 (字节)

NGC     年轻代(young)中当前的容量 (字节)

S0CMX    年轻代中第一个survivor(幸存区)的最大容量 (字节)

S0C  年轻代中第一个survivor(幸存区)的容量 (字节)

S1CMX    年轻代中第二个survivor(幸存区)的最大容量 (字节)

S1C      年轻代中第二个survivor(幸存区)的容量 (字节)

ECMX 年轻代中Eden的最大容量 (字节)

EC     年轻代中Eden 的容量 (字节)

YGC 从应用程序启动到采样时年轻代中gc次数

FGC 从应用程序启动到采样时old代(全gc)gc次数

8、jstat -gcold <pid>:old代对象的信息。

 PC    Perm(持久代)的容量 (字节)

PU     Perm(持久代)目前已使用空间 (字节)

OC     Old代的容量 (字节)

OU     Old代目前已使用空间 (字节)

YGC   从应用程序启动到采样时年轻代中gc次数

FGC   从应用程序启动到采样时old代(全gc)gc次数

FGCT    从应用程序启动到采样时old代(全gc)gc所用时间(s)

GCT 从应用程序启动到采样时gc用的总时间(s)

9、jstat -gcoldcapacity <pid>: old代对象的信息及其占用量。

 OGCMN    old代中初始化(最小)的大小 (字节)

OGCMX    old代的最大容量(字节)

OGC    old代当前新生成的容量 (字节)

OC    Old代的容量 (字节)

YGC  从应用程序启动到采样时年轻代中gc次数

FGC   从应用程序启动到采样时old代(全gc)gc次数

FGCT   从应用程序启动到采样时old代(全gc)gc所用时间(s)

GCT 从应用程序启动到采样时gc用的总时间(s)

10、jstat -gcpermcapacity<pid>: perm对象的信息及其占用量。

 PGCMN    perm代中初始化(最小)的大小 (字节)

PGCMX     perm代的最大容量 (字节)  

PGC     perm代当前新生成的容量 (字节)

PC   Perm(持久代)的容量 (字节)

YGC  从应用程序启动到采样时年轻代中gc次数

FGC   从应用程序启动到采样时old代(全gc)gc次数

FGCT   从应用程序启动到采样时old代(全gc)gc所用时间(s)

GCT 从应用程序启动到采样时gc用的总时间(s)

11、jstat -printcompilation <pid>:当前VM执行的信息。

 Compiled :编译任务的数目.

Size :方法生成的字节码的大小

Type :编译类型

Method :类名和方法名用来标识编译的方法。类名使用/做为一个命名空间分隔符。方法名是给定类中的方法。上述格式是由-XX:+PrintComplation选项进行设置的

jmap

提供堆转储和其他 JVM 内存使用的信息。可以适用于脚本,但堆转储必须在事后分析 工具中使用。一种是heap ByteBuffer,该类对象分配在JVM的堆内存里面,直接由Java虚拟机负责垃圾回收。jmap可分析,一种是direct ByteBuffer是通过jni在虚拟机外内存中分配的。通过jmap无法查看该快内存的使用情况。只能通过top来看它的内存使用情况。

1、jmap -finalizerinfo pid 下面的例子显示等待回收的对象为0个、

2、-heap 打印heap的概要信息,GC使用的算法,heap(堆)的配置及JVM堆内存的使用情况.

jmap -heap  31466

Attaching to process ID 31466, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 24.45-b08

using parallel threads in the new generation. ##新生代采用的是并行线程处理方式
using thread-local object allocation. 指的是本地线程分配缓冲(TLAB,Thread Local Allocation Buffer)。并不是栈上分配(Stack Allocation,HotSpot暂时没有做这项优化)
Mark Sweep Compact GC    标记-清除-压缩GC 算法(Concurrent Mark Sweep 为并行 标记清除)

Heap Configuration:
   MinHeapFreeRatio = 40 最小堆使用比例
   MaxHeapFreeRatio = 70 最大堆可用比例
   MaxHeapSize      = 3221225472 (3072.0MB) 最大堆空间大小
   NewSize          = 268435456 (256.0MB) 新生代分配大小
   MaxNewSize       = 268435456 (256.0MB) 最大生代分配大小
   OldSize          = 5439488 (5.1875MB) 默认老年代大小
   NewRatio         = 2 设置年轻代(包括Eden和两个Survivor区)与年老代的比值(除去持久代)。设置为4,则年轻代与年老代所占比值为1:4,年轻代占整个堆栈的1/5
   SurvivorRatio    = 8  Eden与Survivor的占用比例。例如8表示,一个survivor区占用 1/8 的Eden内存
   PermSize         = 268435456 (256.0MB)永久代大小
   MaxPermSize      = 536870912 (512.0MB)最大永久代大小
   G1HeapRegionSize = 0 (0.0MB)G1 分区的大小

Heap Usage:
New Generation (Eden + 1 Survivor Space):  
   capacity = 241631232 (230.4375MB)  Eden + 正在使用的Survivor 的大小
   used     = 83319048 (79.45923614501953MB)  两者已经使用的大小
   free     = 158312184 (150.97826385498047MB) 空闲大小
   34.48190339897783% used 使用率
Eden Space:
   capacity = 214827008 (204.875MB)   Eden 大小
   used     = 83319048 (79.45923614501953MB)  使用大小
   free     = 131507960 (125.41576385498047MB) 空闲大小
   38.784251931675186% used 使用比例
From Space:  
   capacity = 26804224 (25.5625MB) survior1 区 大小
   used     = 0 (0.0MB)  使用大小
   free     = 26804224 (25.5625MB)  空闲大小
   0.0% used  使用率
To Space:
   capacity = 26804224 (25.5625MB) survior2 区 大小
   used     = 0 (0.0MB) 使用大小
   free     = 26804224 (25.5625MB) 空闲大小
   0.0% used  使用率
tenured generation:
   capacity = 805306368 (768.0MB) 老年代大小
   used     = 141203656 (134.66230010986328MB) 使用大小
   free     = 664102712 (633.3376998901367MB) 空闲大小
   17.534153660138447% used 使用率
Perm Generation:
   capacity = 268435456 (256.0MB) 永久代大小
   used     = 65848376 (62.79790496826172MB) 永久代使用情况
   free     = 202587080 (193.20209503173828MB) 空闲大小
   24.530431628227234% used 使用率

30422 interned Strings occupying 2998704 bytes.  字符串占用多少字节

G1:
Heap Configuration:
   MinHeapFreeRatio         = 40
   MaxHeapFreeRatio         = 70
   MaxHeapSize              = 8589934592 (8192.0MB)
   NewSize                  = 1073741824 (1024.0MB)
   MaxNewSize               = 1073741824 (1024.0MB)
   OldSize                  = 5452592 (5.1999969482421875MB)
   NewRatio                 = 2
   SurvivorRatio            = 10
   MetaspaceSize            = 1073741824 (1024.0MB) 初始元空间大小
   CompressedClassSpaceSize = 1065353216 (1016.0MB) partclass 空间大小
   MaxMetaspaceSize         = 1073741824 (1024.0MB) 最大元空间大小
   G1HeapRegionSize         = 4194304 (4.0MB) 分区的大小

Heap Usage:
G1 Heap:
   regions  = 2048
   capacity = 8589934592 (8192.0MB)
   used     = 1315819008 (1254.86279296875MB)
   free     = 7274115584 (6937.13720703125MB)
   15.318149328231812% used
G1 Young Generation:
Eden Space:
   regions  = 27
   capacity = 1098907648 (1048.0MB)
   used     = 113246208 (108.0MB)
   free     = 985661440 (940.0MB)
   10.305343511450381% used
Survivor Space:
   regions  = 7
   capacity = 29360128 (28.0MB)
   used     = 29360128 (28.0MB)
   free     = 0 (0.0MB)
   100.0% used
G1 Old Generation:
   regions  = 281
   capacity = 7461666816 (7116.0MB)
   used     = 1173212672 (1118.86279296875MB)
   free     = 6288454144 (5997.13720703125MB)
   15.723198327273046% used

23265 interned Strings occupying 2059256 bytes.

3、jmap -histo:live 19570 打印每个class的实例数目,内存占用,类全名信息. VM的内部类名字开头会加上前缀”*”. 如果live子参数加上后,只统计活的对象数量.

使用:jmap -histo <pid>|less 统计大对象

 4、 jmap -permstat pid  输出永久代信息

5、jmap -dump:live,format=b,file=myjmapfile.txt 19570 生成二进制文件在ECLIPSE中打开,使用MAT进行分析(ECLIPSE需要先安装MAT插件)。

jstack

1.在linux环境下,可以通过top命令查看各个进程的cpu使用情况,默认按cpu使用率排序,

2.通过top -Hp 23344(进程id)可以查看该进程下各个线程的cpu使用情况。在top命令中,已经获取到了占用cpu资源较高的线程pid,将该pid转成16进制的值,在thread dump中每个线程都有一个nid,找到对应的nid即可;可以通过printf "%x\n" pid  得到16进制。

 3.通过top命令定位到cpu占用率较高的线程之后,继续使用jstack pid命令查看当前java进程的堆栈状态。jstack 31466|grep 16进制 -A 30 

jstack命令生成的thread dump信息包含了JVM中所有存活的线程,

在dump中,线程一般存在如下几种状态:
1、RUNNABLE,线程处于执行中
2、BLOCKED,线程被阻塞synchronized关键字
3、WAITING,线程正在无限等待唤醒
4、TIMED_WAITING 线程在等待唤醒,但设置了时限

实例1:多线程竞争synchronized锁

很明显:线程1获取到锁,处于RUNNABLE状态,线程2处于BLOCK状态
1、locked <0x000000076bf62208>说明线程1对地址为0x000000076bf62208对象进行了加锁;
2、waiting to lock <0x000000076bf62208> 说明线程2在等待地址为0x000000076bf62208对象上的锁;
3、waiting for monitor entry [0x000000001e21f000]说明线程1是通过synchronized关键字进入了监视器的临界区,并处于"Entry Set"队列,等待monitor。

 线程1和2都处于WAITING状态
1、线程1和2都是先locked <0x000000076bf62500>,再waiting on <0x000000076bf62500>,之所以先锁再等同一个对象,是因为wait方法需要先通过synchronized获得该地址对象的monitor;
2、waiting on <0x000000076bf62500>说明线程执行了wait方法之后,释放了monitor,进入到"Wait Set"队列,等待其它线程执行地址为0x000000076bf62500对象的notify方法,并唤醒自己,
jinfo

命令可以用来查看 Java 进程运行的 JVM 参数

jcmd

它用来打印 Java 进程所涉及的基本类、线程和 VM 信息。它适用于脚本,可以像这 样执行:

% jcmd process_id command optional_arguments

jcmd help 可以列出所有的命令。jcmd help <command> 可以给出特定命令的语法。

jconsole

提供 JVM 活动的图形化视图,包括线程的使用、类的使用和 GC 活动。

jhat

读取内存堆转储,并有助于分析。这是事后使用的工具。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值