linux中怎么根据java内存地址映射资源

写在前面,上周五布置渠道服务器,起初四个区服,周六一天都没有意外。周日新增五个区服,从此开始了一场噩梦,区服频繁崩溃。linux崩溃之后几乎不能登陆,shell也几乎无法执行,绝大多数情况下只能通过云服后台重启。上线排查问题,报错日志只有一个,没有资源启动线程。监控linux线程数量,会持续增长到12000个以上,耗尽了资源之后就崩溃。考虑到线上已经运营,只能先扔一个监控线程并且自起的shell脚本在服务器上。秒起对线上影响几乎不太大,勉强续命。来到内网测试线程,经过了两天两夜的排查,对比了几个版本的SVN,测试了JVM内存,Maven的各种特性。打印了线程栈,设想了死锁。排查了服务器使用的五种数据库,是的,这个项目使用了五种数据库。于昨晚凌晨一点发现,每个区服的线程池大小设置为核心数*100,我们机器是16核的,每个区服需要开1600个线程九个区服共计15000左右,由于Java是大线程,开到12000的时候就资源就已经不足了。使用的是Netty的框架,因为我不是做Java的,所以在这里也有一个疑问,Netty的线程池运作不是先找可用的,而是优先把线程池开满吗?修改线程池数量之后稳定。
接下来看看怎么根据linux打印出来的线程栈中的内存地址定位到java中的类或者资源。

(1) jps 命令 定位Java进程id

jps是jdk提供的一个用来查看java进程信息的小工具,无需额外安装。因为我们只需要获得java的进程id,所以不需要带参数。带参数的有兴趣可以自己找找,也可以使用ps命令,根据个人习惯了。jps效果如下:
linux中怎么根据java内存地址映射资源

(2) ps 命令查看这个进程此刻线程数量

ps -eLf | grep 71223 | wc -l
linux中怎么根据java内存地址映射资源

(3) 打印java线程栈的dump文件

jmap -dump:file=heapdump.hprof 71223
运行命令后得到一个heapdump.hprof的dump文件,无法阅读。

(4) VisualVM 开始加载文件

博主使用的是mac版本,版本号为1.4.4
打开dump文件
linux中怎么根据java内存地址映射资源
选择OQL Console,OQL是JVM的对象查询语言。具体了解不太多,选择这个是因为配合内存地址查询。当然也可以选择Threads或者Objects进行查看,这个工具很有用。前端后端我觉得都可以看看
linux中怎么根据java内存地址映射资源
到这个地方线程栈的信息就已经准备好了,接下来我们还要一份可读的线程信息。

(5) jstack

jstack -l 71223 > stack.log
这个命令得到一份stack.log的日志文件。使用日志查看器或者编辑器都可以查看,在这里面我们可以得到那些资源存在死锁,哪些资源消耗大内存之内的。当然,还有每个线程的内存地址。内容如下
linux中怎么根据java内存地址映射资源
这些地址就是我们需要的,接下来回到VisualVM。

(6) 通过地址定位Java代码

linux中怎么根据java内存地址映射资源
1.输入语句
2.执行
3.就是结果,图中ServerDaemon.java 中的bossGroup就是我们定位到的代码。