使用Jhat排查问题实战:查看类型为List的静态字段的大小

原创 吴就业 113 0 2019-03-05

本文为博主原创文章,未经博主允许不得转载。

本文链接:https://wujiuye.com/article/b8f3c8aa0a004dccad113ff17d5ed5b4

作者:吴就业
链接:https://wujiuye.com/article/b8f3c8aa0a004dccad113ff17d5ed5b4
来源:吴就业的网络日记
本文为博主原创文章,未经博主允许不得转载。

本篇文章写于2019年03月05日,从公众号手工同步过来(博客搬家),本篇为原创文章。

今天碰到一个问题,系统后台首页数据不展示了。我使用浏览器的开发者功能,找到api,确实服务器返回给浏览器的结果是空数据。然后我顺藤摸瓜找到了这个api的代码,结果发现又是使用的内存缓存。

public class TaskStatic {
    public static List<PostbackLogBean> payoutlistAffHour;
}

所以我就想,居然没有数据,那我就看看缓存对象payoutlistAffHour是否有数据。

此时,我需要一个强大的工具,I need a powerful tool !我需要查看payoutlistAffHour这个List的size值。

注意,如果你用VisualVM工具分析,你是得不到TaskStatic这个对象的,因为TaskStatic根本没有被实例化,只是用到TaskStatic类的静态字段,所以TaskStatic在堆中不存在实例对象。

dump堆内存数据,下载到本地

在服务器上dump堆内存信息。

jmap -dump:live,file=current_object_in_memory_info.dump pid

其中file=current_object_in_memory_info.dump 是用于存储堆内存信息的文件,文件名为current_object_in_memory_info.dump,可以自己随便取。pid则是目标进程的进程id。执行完这条指令之后将文件下载到本机电脑,不要在远程服务器上分析,免得增加服务器压力。

通过 Jhat分析目标对象

如何借助JHat的强大功能查看类型为List的静态字段的大小。

打开终端,进入到,从服务器上下载下来的dump堆内存信息文件所在目录,如current_object_on_memory.dump所在的目录。然后执行下面这条jhat指令。

>jhat current_object_on_memory.dump

等待jhat执行成功后,就可以在浏览器中输入“http://localhost:7000”访问jhat,查看jhat的分析结果。得要有目的性的查看,按“command+f”输入目标对象,最好输入包名,可以快速准确定位到目标。如下图。

图片

找到目标类后,点击该类名,跳转到class详情页。

图片

class详情页,列出了该类的父类、加载它的类加载器等信息,如果该类有子类则还会列出所有子类。现在我要重点关注的是“Instance Data Members” 这部分的数据,可理解为类的实例的字段数据,包括静态字段。

图片

从上图中可以找到payoutlistAffHour字段,该字段是一个ArrayList类型,没有错。有下划线说明是个链接,点击跳转到该字段的详情数据页。

图片

上图对象详情页的size就是该静态List的大小,很显然并没有数据。

既然内存中没有对应的数据,那么病根就可以追溯到上一层了,是哪里给这个静态字段赋的值。

#后端

声明:公众号、CSDN、掘金的曾用名:“Java艺术”,因此您可能看到一些早期的文章的图片有“Java艺术”的水印。

文章推荐

公司项目中的代码为什么会烂得像一坨SHI

不要再抱怨你们公司项目的代码写得多烂,因为你不了解它的历史,你没有参与它的成长,你根本就不懂它是怎么长残的。

使用Sharding-JDBC实现分表,并让动态数据源支持Sharding-JDBC数据源

本篇介绍了笔者在一个业务场景下,通过各种优化手动都无法降低查询耗时的情况下,选择将表拆分多个,并使用Sharding-JDBC实现分表的查询,并介绍如何在已经实现了多数据源的项目中支持Sharding-JDBC数据源。

使用Jprofiler远程监控线上服务

需要特别注意的一点是,本地安装的Jprofiler图形界面工具一定要与远程服务器安装的版本号一致。否则远程连接就连接不了。

JVM方法表、栈桢、局部变量表、操作数栈的理解

看懂Java字节码首先得要了解栈桢和方法表,这两个知识点是比较重要的。另外了解这两个知识点还有助于指导Java性能调优工作。

Redis数据持久化策略

我们可以通过修改redis.conf配置文件来选择使用持久化策略,redis提供了三种持久化策略:RDB快照、AOF(Append-only file)、混合策略。

ConcurrentHashMap是如何实现线程安全的

ConcurrentHashMap 在1.7中 实现线程安全是通过锁住Segment对象的。而在1.8 中则是针对首个节点(table[hash(key)]取得的链接或红黑树的首个节点)进行加锁操作。