插: 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。 
坚持不懈,越努力越幸运,大家一起学习鸭~~~

3妹:早,2哥,教师节加中秋节快乐哈。看你这些天教我学java的份上,也算是我的老师了,呐,送你的教师节礼物。
2哥:呀,没想到3妹还送我礼物,是什么呀。
3妹:打开看看不就知道了。
2哥:原来是一个保温杯。
3妹:程序员工作压力大,2哥要懂得养生,多喝热水,哈哈。
2哥:这个我还真的需要,前天还看一个大学老师,用老干妈杯子喝水上热搜了。
3妹:老师这个行业还是有很多好老师的,不在意这些生活的细节,把心思主要用在教书育人上面。
2哥:是的。看在你送我礼物的份上,今天再教你一些JVM调优的方式吧。

jstat

jstat可以打印出当前JVM运行的各种状态信息,例如新生代内存使用情况,老年代内存使用情况,以及垃圾回收的时间。Minor GC发生总次数,总耗时,Full GC发生总次数,总耗时。(jmap -heap命令也可以打印出堆中各个分区的内存使用情况,但是不能定时监测,持续打印。例如每1s打印当前的堆中各个分区的内存使用情况,一直打印100次。)

//5828是java进程id,1000是打印间隔,每1000毫秒打印一次,100是总共打印100次
jstat -gc 5828 1000 100

打印结果如下:

各个参数的含义如下:

S0C 新生代中第一个survivor(幸存区)的总容量 (字节)

S1C新生代中第二个survivor(幸存区)的总容量 (字节)

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

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

EC 新生代中Eden区的总容量 (字节)

EU 新生代中Eden区目前已使用空间 (字节)

OC 老年代的总容量 (字节)

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

YGC 目前新生代垃圾回收总次数

YGCT 目前新生代垃圾回收总消耗时间

FGC 目前full gc次数总次数

FGCT 目前full gc次数总耗时,单位是秒

GCT 垃圾回收总耗时

一般还可以使用jstat -gcutil <pid>:统计gc信息,这样打印出来的结果是百分比,而不是实际使用的空间,例如jstat -gcutil 1 1000 100

例如,S0代表 新生代中第一个survivor区的空间使用了73.19%,E代表新生代Eden区使用了51%,O代表老年代使用了98%

参数 描述
S0 年轻代中第一个survivor(幸存区)已使用的占当前容量百分比
s1 年轻代中第二个survivor(幸存区)已使用的占当前容量百分比
E 年轻代中Eden已使用的占当前容量百分比
O old代已使用的占当前容量百分比
M 元空间(MetaspaceSize)已使用的占当前容量百分比
CCS 压缩使用比例
YGC 年轻代垃圾回收次数
FGC 老年代垃圾回收次数
FGCT 老年代垃圾回收消耗时间
GCT 垃圾回收消耗总时间

jstack

jstack可以生成当前JVM的线程快照,也就是当前每个线程当前的状态及正在执行的方法,锁相关的信息。jstack -l 进程id,-l代表除了堆栈信息外,还会打印锁的附加信息。jstack还会检测出死锁信息。一般可以用于定位线程长时间停顿,线程间死锁等问题。

例如在下面的例子中,第一个线程获取到lock1,再去获取lock2,第二个线程先获取到lock2,然后再去获取lock1。每个线程都只获得了一个锁,同时在获取另外一个锁,就会进入死锁状态。

public static void main(String[] args) {final Integer lock1 = new Integer(1);final String  lock2 = new String();ExecutorService executorService = Executors.newCachedThreadPool();executorService.execute(new Runnable() {@Overridepublic void run() {synchronized (lock1) {System.out.println("线程1获得了lock1");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("线程1休眠结束");System.out.println("线程1开始尝试获取lock2");synchronized (lock2) {System.out.println("线程1获得了lock2");}}}});executorService.execute(new Runnable() {@Overridepublic void run() {synchronized (lock2) {System.out.println("线程2获得了lock2");System.out.println("线程2开始尝试获取lock1");synchronized (lock1) {System.out.println("线程2获得了lock2");}}}});}

使用jstack -l 进程id就可以打印出当前的线程信息

以及各个线程的状态,执行的方法(pool-1-thread-1和pool-1-thread-2分别代表线程池的第一个线程和第二个线程):

jmap

jmap -heap

这个命令可以生成当前堆栈快照。使用 jmap -heap 进程id可以打印出当前堆各分区内存使用情况的情况,新生代(Eden区,To Survivor区,From Survivor区),老年代区的内存使用情况。

使用jmap -heap查看内存使用情况的案例

jmap -histo

jmap -histo 进程id 打印出当前堆中的对象统计信息,包括类名,每个类的实例数量,总占用内存大小。

instances列:表示当前类有多少个实例。
bytes列:说明当前类的实例总共占用了多少个字节
class name列:表示的就是当前类的名称,class name 对于基本数据类型,使用的是缩写。解读:B代表byte ,C代表char ,D代表double, F代表float,I代表int,J代表long,Z代表boolean
前边有[代表数组,[I 就相当于int[]
对象数组用`[L+类名`表示

jmap -dump

使用jmap -dump:format=b,file=dump.hprof 进程id可以生成当前的堆栈快照,堆快照和对象统计信息,对生成的堆快照进行分析,可以分析堆中对象所占用内存的情况,检查大对象等。执行jvisualvm命令打开使用Java自带的工具Java VisualVM来打开堆栈快照文件,进行分析。可以用于排查内存溢出,内存泄露问题。在Java VisualVM里面可以看到每个类的实例对象占用的内存大小,以及持有这个对象的实例所在的类等等信息。

也可以配置启动时的JVM参数,让发送内存溢出时,自动生成堆栈快照文件。

//出现 OOM 时生成堆 dump:
-XX:+HeapDumpOnOutOfMemoryError
//生成堆文件地址:
-XX:HeapDumpPath=/home/liuke/jvmlogs/

使用jmap -dump:format=b,file=/存放路径/heapdump.hprof 进程id就可以得到堆转储文件,然后执行jvisualvm命令就可以打开JDK自带的jvisualvm软件。

例如在这个例子中会造成OOM问题,通过生成heapdump.hprof文件,可以使用jvisualvm查看造成OOM问题的具体代码位置。

public class Test018 {ArrayList<TestObject> arrayList = new ArrayList<TestObject>();public static void main(String[] args) {Test018 test018 =new Test018();Random random = new Random();for (int i = 0; i < 10000000; i++) {TestObject testObject = new TestObject();test018.arrayList.add(testObject);}}private static class TestObject {public byte[] placeholder = new byte[64 * 1024];//每个变量是64k}
}-Xms20m -Xmx20m -verbose:gc -XX:+PrintGCDetails -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/存放路径/heapdump.hprof

造成OOM问题的代码位置:

堆内对象列表

占用内存最多的实例对象就是这个placeholder对象

MAT

MAT主要可以用于分析内存泄露,可以查询dump堆转储文件中的对象列表,以及潜在的内存泄露的对象。

通过导入hprof文件,主页会展示潜在的内存泄露问题,比如下面这个例子中

public class Test018 {static ArrayList<TestObject> arrayList = new ArrayList<TestObject>();public static void main(String[] args) {Random random = new Random();for (int i = 0; i < 10000000; i++) {TestObject testObject = new TestObject();Test018.arrayList.add(testObject);}}private static class TestObject {public byte[] placeholder = new byte[64 * 1024];}
}

在详情页面Shortest Paths To the Accumulation Point表示GC root对象到内存消耗聚集点的最短路径,内存聚集点的意思就是占用了大量内存的对象,也就是可能发生; 内存泄露的对象。

然后在主页点击Histogram,进入Histogram页面可以看到对象列表,with incomming references 也就是可以查看所有对这个对象的引用(思路一般优先看占用内存最大对象;其次看数量最多的对象。)。我们这个例子中主要是byte[]数组分配了占用了大量的内存空间,而byte[]主要来自于Test018类的静态变量arrayList的每个TestObject类型的元素的placeholder属性。

同时可以点击 内存快照对比 功能对两个dump文件进行对比,判断两个dump文件生成间隔期间,各个对象的数量变化,以此来判断内存泄露问题。

【教3妹学java】JVM调优有哪些工具?相关推荐

  1. java jvm调优_(第2部分,共3部分):有关性能调优,Java中的JVM,GC,Mechanical Sympathy等的文章和视频的摘要...

    java jvm调优 这是以前的文章(第3部分,共1部分)的继续:有关性能调优,Java中的JVM,GC,Mechanical Sympathy等的文章和视频的提要 . 事不宜迟,让我们开始使用我们的 ...

  2. java jvm调优_(第1部分,共3部分):有关性能调优,Java中的JVM,GC,Mechanical Sympathy等的文章和视频的摘要...

    java jvm调优 我已经花了几个月的时间考虑审查有关性能调优,JVM,Java中的GC,Mechanical Sympathy等主题的文章和视频的缓存,并最终花了点时间–也许这就是重点我什么时候才 ...

  3. java jvm调优面试题_【Java面试题第一期】有没有jvm调优经验?调优方案有哪些?...

    ​1. 调优时机: a. heap 内存(老年代)持续上涨达到设置的最大内存值: b. Full GC 次数频繁: c. GC 停顿时间过长(超过1秒): d. 应用出现OutOfMemory 等内存 ...

  4. java JVM调优总结 -Xms -Xmx -Xmn -Xss

    为什么80%的码农都做不了架构师?>>>    堆大小设置 JVM 中最大堆大小有三方面限制:相关操作系统的数据模型(32-bt还是64-bit)限制:系统的可用虚拟内存限制:系统的 ...

  5. 【教3妹学java】类加载的过程是什么样的?

    插: 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家.点击跳转到网站.  坚持不懈,越努力越幸运,大家一起学习鸭~~~ 2哥:"今天只有残留的躯壳,迎接光辉 ...

  6. 【教3妹学java】2.引用数据类型

    2哥:3妹,昨天教你的java基本数据类型 掌握了吗? 3妹:掌握了,java有8大基本类型(byte,short,char,int,long,float,double,boolean)-- 2哥:我 ...

  7. JVM调优三板斧,快速掌握调优的核心与思路

    如何从调优小白走向调优高手 说起JVM调优,大伙儿可能瞬间头皮发麻."好家伙,和调优沾边儿的事儿,不是我这个段位的小新手能解决的". 于是赶紧找来了技术大拿,看大拿三下五除二排查出 ...

  8. jvm系列(四):jvm调优-命令大全(jps jstat jmap jhat jstack jinfo)

    2019独角兽企业重金招聘Python工程师标准>>> 文章同步发布于github博客地址,阅读效果更佳,欢迎品尝 运用jvm自带的命令可以方便的在生产监控和打印堆栈的日志信息帮忙我 ...

  9. jvm系列(四):jvm调优-命令篇

    运用jvm自带的命令可以方便的在生产监控和打印堆栈的日志信息帮忙我们来定位问题!虽然jvm调优成熟的工具已经有很多:jconsole.大名鼎鼎的VisualVM,IBM的Memory Analyzer ...

  10. 教妹学Java(六):JDK,JRE和JVM之间有什么区别?

    大家好,我是沉默王二.本篇文章通过我和三妹的对话来谈一谈"JDK,JRE 和 JVM 之间的区别".本文付费,为表谢意,附送上个人微信(qing_gee),坑位所剩无几,快加,你有 ...

最新文章

  1. fork/join 全面剖析,你可以不用,但是不能不懂!
  2. 算法----斐波那契数
  3. iOS 绘制圆角矩形
  4. Canvas做股票数据走势图实践分享(一)
  5. ML.NET Cookbook:(7)如何训练回归模型?
  6. ArcGIS实验教程——实验二十二:空间数据符号化
  7. [poj3321]Apple Tree_dfs序_树状数组
  8. 一个人长途自驾旅行需要注意什么?
  9. mysql面试题 真的很不错
  10. 统计一句话中每个字母出现的次数
  11. [Effective JavaScript 笔记] 第7条:视字符串为16位的代码单元序列
  12. 基于java的图书管理系统(英文)
  13. cassandra 避免 allow filter 提升性能的方法
  14. Nginx 启动报 bind() to 0.0.0.0:XXXX failed (13: Permission denied)
  15. C#效验身份证号是否正确
  16. MATLAB 动态曲线 视频
  17. 一整套自助点餐软件,包含微信端,电视机,后台管理程序,个人开发,全套源码
  18. 继神州行10元包月后:北京动感地带资费降至6元/月
  19. 在 Oracle Enterprise Linux 和 iSCSI 上构建您自己的 Oracle RAC 集群(续)
  20. “晓白”学python-科普篇(2)-人们都用python做什么?

热门文章

  1. 迷失lost结局什么意思_迷失 美剧 结局是什么
  2. win7下pytorch-gpu安装
  3. BZOJ_3772_精神污染_主席树
  4. 【BZOJ3772】精神污染 DFS序+主席树
  5. pcntl php windows_PHP各版本安装pcntl扩展
  6. 超级详细的vue2学习笔记
  7. 周集中团队Nature子刊中网络图布局的R语言可视化复现
  8. manjaro linux树莓派,manjaro
  9. CentOS6 Samba服务器配置
  10. 好123主页篡改修复方法