现实企业级java开发中,有时候我们会碰到下面这些问题:
- OutOfMemoryError内存不足
- 内存泄露
- 线程死锁
- 锁争用(lock Contention)
- Java进程消耗CPU过高
- ... ... 等等
TIME列就是各个Java线程耗费CPU时间,CPU时间最长的线程ID为21742的线程,用【printf "%x\n" 21742】得到21742的十六进制为54ee,下面会用到。 下一步终于轮到jstack上场了,他用来输出进程21711的线程,然后根据线程ID的十六进制值grep,如下: 可以看到CPU消耗在PollIntervalRetrySchedulerThread这个类的Object.wait(),找到该代码,定位到下面的代码: 它是轮训任务的空闲等待代码,上面的sigLock.wait(timeUntilContinue)就对应了前面的Object.wait。 三、jmap(Memory Map)和jhat(java heap Analysis tool) jmap用来查看堆内存使用状况,一般结合jhat使用。 jmap的语法格式如下: 如果运行在64位JVM上,可能需要指定-j-d64命令选项参数。 打印进程的类加载器和类加载器的持久代对象信息,输出:类加载器名称、对象是否存活(不可靠)、对象地址、父类加载器、已加载的类大小等信息,如下图:
使用jmap -heap pid查看进程堆内存使用情况,包括使用的GC算法、堆配置参数和各代中堆内存使用情况。比如下面的例子: 使用jmap -histo[:live] pid查看堆内存中的对象数目、大小统计直方图,如果当上live则只统计活对象,如下: class name是对象类型,说明如下: 还有一个很常用的情况是:用jmap把内存使用情况dump到文件中,在用jhat分析查看。jmap进行dump命令格式如下: 例如对上面ID为21711进行dump: dump出来的文件可以使用mat、VisualVM等工具查看,这里用jhat查看: 注意如果dump文件太大,可能需要加上-J-Xmx512m这种参数指定最大堆内存,即jhat -J-Xmx512m -port 9998 /tmp/dump.dat。然后可以在浏览器中输入主机地址:9998查看了,如下:
上面红线框出来的部分大家可以自己去探索下,最后一项是支持OQL(对象查询语言) 四、jstat(JVM统计监测工具) 语法格式如下: vmid是java虚拟机ID,在linux/unix系统上一般就是进程ID。interval是采样时间间隔。count是采样数目。比如下面输出的GC信息,采样时间间隔为250ms,采样数为4: 要明白上面各列的意义,先看JVM堆内存布局: 可以看出: 现在来解释各列含义: 五、hprof(Heap/CPU Profiling Tool) hprof能够展现CPU使用率,统计堆内存使用情况。语法格式如下: 完成的命令选项如下: 来几个官方指南的例子:CPU Usage Sampling Profiling(cpu=samples)的例子 上面间隔20毫秒采样cpu消耗信息,堆栈深度为3,生成的profile文件名称为java.hprof.txt,在当前目录。 CPU Usage Times Profiling(cpu=times)的例子,它相对于CPU Usage Sampling Profile能够获得更细粒度的CPU消耗信息,能够细到每个方法调用的开始和结束,它的实现使用了字节码注入技术: Heap Allocation Profiling(heap=sites)的例子: Heap Dump(heap=dump)的例子,它比上面的Heap Allocation Profiling能生成更详细的heap dump信息: 虽然在jvm启动参数中加入-Xrunprof:heap=sites参数可以生成cpu/heap profile文件,但对jvm性能影响非常大,不建议在线上服务器环境使用。 转子:https://my.oschina.net/feichexia/blog/196575