共计 12559 个字符,预计需要花费 32 分钟才能阅读完成。
一篇 Sun 项目主页上介绍 JConsole 使用的文章,前段时间性能测试的时候大概翻译了一下以便学习,今天整理一下发上来,有些地方也不知道怎么翻,就保留了原文,可能还好理解点,呵呵,水平有限,翻的不好,大家多多包涵。
JConsole 毕竟是 JDK 自带的东西,功能虽然没有一些商业软件那么强大,但是稳定性好,在大压力情况下也不会发生什么问题。而且,提供了相对全面的系统监控功能,还是值得一用的。
JConsole
JConsole 是一个基于 JMX 的 GUI 工具,用于连接正在运行的 JVM,不过此 JVM 需要使用可管理的模式启动。如果要把一个应用以可管理的形式启动,可以在启动是设置com.sun.management.jmxremote
。例如,启动一个可以在本地监控的 J2SE 的应用Java2Demo,需输入以下命令:
JDK_HOME/bin/java -Dcom.sun.management.jmxremote -jar JDK_HOME/demo/jfc/Java2D/Java2Demo.jar JDK_HOME 需要
是一个含有 JDK5.0 的目录。
要启动 JConsole,运行 JDK_HOME/bin/jconsole 一个用于连接的对话框将会打开。对话框的 Local 标签列出了所有本地正在运行的 JVM,还包含进程的 ID 等信息。
Figure 2: Local Tab.
JConsole 可以以三种方式连接正在运行的 JVM:
- Local:使用 JConsole 连接一个正在本地系统运行的 JVM,并且执行程序的和运行 JConsole 的需要是同一个用户。JConsole 使用文件系统的授权通过 RMI 连接器连接到平台的 MBean 服务器上。这种从本地连接的监控能力只有 Sun 的 JDK 具有
- Remote:使用下面的 URL 通过 RMI 连接器连接到一个 JMX 代理:
service:jmx:rmi:///jndi/rmi://hostName:portNum/jmxrmi
hostName填入主机名称,portNum为 JMX 代理启动时指定的端口。JConsole 为建立连接,需要在环境变量中设置 mx.remote.credentials 来指定用户名和密码从而进行授权。
- Advanced:使用一个特殊的 URL 连接 JMX 代理。一般情况使用自己定制的连接器而不是 RMI 提供的连接器来连接 JMX 代理,或者是一个使用 JDK1.4 的实现了 JMX 和 JMX Rmote 的应用。
当 JConsole 成功建立连接,它从连接上的 JMX 代理处获取信息,并且以下面几个标签页呈现信息。
- Summary tab. 监控 JVM 和一些监控变量的信息。
- Memory tab. 内存使用信息
- Threads tab. 线程使用信息
- Classes tab. 类调用信息
- VM tab. JVM 的信息
- MBeans tab.所有 MBeans 的信息
MBeans tab 展示了所有以一般形式注册到 JVM 上的 MBeans。MBeans tab 允许你获取所有的平台信息,包括那些不能从其他标签页获取到的信息。注意,其他标签页上的一些信息也在 MBeans 这里显示。另外,你可以使用 MBeans 标签管理你自己的应用的 MBeans
使用 MBeans Tab 监控和管理 MBean
注册到 JMX 代理的平台或者应用的 MBeans,可以通过 MBeans 标签获取。例如, 内存的 MBeans 如下面定义
public interface MemoryMXBean {public MemoryUsage getHeapMemoryUsage();
public MemoryUsage getNonHeapMemoryUsage();
public int getObjectPendingFinalizationCount();
public boolean isVerbose();
public void setVerbose(boolean value);
public void gc();}
内存的 MBean 包括四个属性:
HeapMemoryUsage
. 用于描述当前堆内存使用情况的只读属性NonHeapMemoryUsage
. 用于描述当前的非堆内存的使用情况的只读属性ObjectPendingFinalizationCount
.用于描述有多少对象被挂起以便回收。Verbose
.用于动态设置 GC 是否跟着详细的堆栈信息,为一个布尔变量
内存的 MBean 支持一个操作——GC,此操作可以发送进行实时的垃圾回收请求。
Figure 3: MBeans Tab.
左边的树形结构以名字的方式展示了所有 MBeans 的列表。一个 MBean 对象的名字由一个域的名字和一串关键字属性组成。例如,JVM 的平台的 MBeans 是在“java.lang”域下的一组,而日志的 MBeans 则在 ”java.util.logging
“ 域下。MBean 对象的名字在 javax.management.ObjectName 规范中定义。
当你在树中选中一个 MBean,属性,方法,或者通知等一些信息会再右边显示出来。如果属性是可写的(属性被标志为蓝色),你可以进行设置。你可以操作在 Operations tab 中列出的操作。你也可以看到由 MBean 发送出来的通知:默认情况,如果你不订阅通知的话,JConsole 不会收到 MBean 发生过来的通知。你可以点击 "Subscribe
“(订阅) 按钮来堆通知进行定义,而使用 ”Unsubscribe
“ 按钮来取消订阅
Figure 4: MBeans Notification.
监控内存
内存标签页通过读取内存系统、内存池、垃圾回收的 MBean 来获取对内存消耗、内存池、垃圾回收的情况的统计。
图:
上图展示了内存随时间变化的使用情况。有对堆的、非堆的以及特殊内存池的统计。内存池信息是否能被获取,取决与使用的 Java 虚拟机。下面列表展示了 HotSpot 虚拟机的内存池情况。
Eden Space (heap): 内存最初从这个线程池分配给大部分对象。
Survivor Space (heap):用于保存在 eden space 内存池中经过垃圾回收后没有被回收的对象。
Tenured Generation (heap):用于保持已经在 survivor space 内存池中存在了一段时间的对象。
Permanent Generation (non-heap): 保存虚拟机自己的静态 (refective) 数据,例如类(class)和方法(method)对象。Java 虚拟机共享这些类数据。这个区域被分割为只读的和只写的,
Code Cache (non-heap):HotSpot Java 虚拟机包括一个用于编译和保存本地代码(native code)的内存,叫做“代码缓存区”(code cache)
详细信息区域给出一些当前线程的信息:
Used:已使用:当前的内存使用量。使用的内存包括所有对象(能被获取和不能被获取的)所占用的内存。
Committed:分配量:Java 虚拟机保证能够获取到的内存量。分配内存(committedmemory)的量可能随时间改变。Java 虚拟机可能释放部分这里的内存给系统,相应的分配的内存这时可能少于初始化时分配的给它的量。分配量总数大于或等于已使用的内存量。
Max :内存管理系统可以使用的最大内存量。这个值可以被改变或者不做设定。如果 JVM 试图增加使用的内存到大于分配量(committedmemory)的情况,内存分配可能失败,即便想使用的内存量小于或者等于最大值(如:系统虚拟内存比较低时)
Usage Threshold The usage threshold of a memory pool. This field will only beshown if the memory pool supports usage threshold.
GC time :垃圾回收使用的总时间和调用垃圾回收的次数。它可能有好几行,每行代表 JVM 使用的垃圾回收算法。(
右下角的棒状图表显示了被 JVM 的内存池消耗的内存。如果内存使用超过 usage threshold, 则棒会变红。usagethreshold 是用于支持内存检查的 Memory Pool MBean 的一个属性。MemoryPoolMXBean 定义了一系列方法用于检查内存。
public interface MemoryPoolMXBean {
….
// Usage threshold
public long getUsageThreshold();
public void setUsageThreshold(long threshold);
public boolean isUsageThresholdExceeded();
public boolean isUsageThresholdSupported();
// Collection usage threshold
public long getCollectionUsageThreshold();
public void setCollectionUsageThreshold(long threshold);
public boolean isCollectionUsageThresholdSupported();
public boolean isCollectionUsageThresholdExceeded();
}
每种内存池可能有两种内存初始话支持:usage threshold 和 collection usage threshold 特殊的内存池可能两种都不支持。
Usage Threshold
usage threshold是内存池中一个可管理的属性。它使用低负荷的内存监控。设置 usage threshold 为正值则 usage threshold 检查内存池。设置 usage threshold 为零,则关闭检查。默认值由 JVM 设置。JVM 一般让 usage threshold 在最合适的时候检查内存,典型的在 GC 的过程中和某些分配内存的时候。如果 JVM 发现当前的内存使用超过了 usage threshold, 它将会把 UsageThresholdExceeded
属性设置为 true
有些内存池可能不支持 usage threshold。 你可以使用 UsageThresholdSupported 属性来判断一个内存池是否支持
usage threshold。 例 如,一个比较完善(generational garbage collector)的垃圾回收器(如 HotSpot 的虚拟机),most of the objects are allocated in the young generation,从 eden 内存池中产生。eden pool 被设计成可以被装满;再 eden pool 中执行垃圾回收将会释放他
更多详情见请继续阅读下一页的精彩内容:http://www.linuxidc.com/Linux/2015-02/113417p2.htm
Collection Usage Threshold
Collection usage threshold是可进行垃圾回收的内存池的一个可配置属性。JVM 堆一个内存池进行 垃圾回收以后,此内存池中的一些内存仍然被那些没有被回收的对象占用。collection usage threshold 仅允许你在垃圾回收后对内存进行检查。如果 JVM 发现可用内存超出 collection usage threshold,它将会设置 CollectionUsageThresholdExceeded
属性为 true。
你可以使用 CollectionUsageThresholdSupported
属性来控制内存池释放支持 collection usage threshold.
usage threshold 和 collection usage threshold 是 MBean 标签中的一组。例如,在左边的树形结构中选择 TenuredGen,设置 tenured generation memory pool 的 usage threshold 为 6m。如下图所示
Figure 6: Setting Usage Threshold.
当 TenuredGen
memory pool 的内存使用超过 6MBytes 时,代表 TenuredGen
memory pool 的柱状图将会呈现红色来代表使用的内存超过了 usage threshold。代表堆内存的柱状图也将变为红色。你可以选择柱状图或者在图表中指定内存池来查看某个指定内存池的信息。如果把鼠标房子柱状图上,将会显示出内存池的名字
Figure 7: Low Memory.
开启 / 关闭虚拟机的详细跟踪
如上所述,内存系统的 MBean 定义了一个叫做 Verbose 布尔变量,让你能动态的打开或关闭详细的 GC 跟踪。详细的 GC 跟踪,将会在 JVM 启动时显示。默认的 HotSpot 的 GC 详细输出为stdout
.
Figure 8: Setting Verbose GC.
死锁检查
线程标签页提供关于应用的线程运行信息
Figure 9: Threads Tab.
左下角列出了所以正在运行的线程。如果你在过滤器中输入一个字符,线程列表将仅显示线程名字包含你输入字符的线程。通过点击某个线程,你可以获取这个线程的相关信息。
线程的 MBean 标签提供了一些 Thread 标签没有提供有用的操作。
findMonitorDeadlockedThreads
. 如果发生线程死锁,可以通过这个检查出来。操作返回一组死锁的线程 IDgetThreadInfo
. 返回线程的信息。包括线程的名称、堆栈信息,导致当前线程阻塞的锁,如果有的话,还返回哪儿线程持有这个锁,和这个线程信息的统计。getThreadCpuTime
. 返回指定线程消耗的 CPU 时间。
为使用上面这些属性,可以到 MBeans 标签下,在 MBeans 树上选择 Threading MBean。它列出了当前监控的 JVM 所有属性的操作。
一篇 Sun 项目主页上介绍 JConsole 使用的文章,前段时间性能测试的时候大概翻译了一下以便学习,今天整理一下发上来,有些地方也不知道怎么翻,就保留了原文,可能还好理解点,呵呵,水平有限,翻的不好,大家多多包涵。
JConsole 毕竟是 JDK 自带的东西,功能虽然没有一些商业软件那么强大,但是稳定性好,在大压力情况下也不会发生什么问题。而且,提供了相对全面的系统监控功能,还是值得一用的。
JConsole
JConsole 是一个基于 JMX 的 GUI 工具,用于连接正在运行的 JVM,不过此 JVM 需要使用可管理的模式启动。如果要把一个应用以可管理的形式启动,可以在启动是设置com.sun.management.jmxremote
。例如,启动一个可以在本地监控的 J2SE 的应用Java2Demo,需输入以下命令:
JDK_HOME/bin/java -Dcom.sun.management.jmxremote -jar JDK_HOME/demo/jfc/Java2D/Java2Demo.jar JDK_HOME 需要
是一个含有 JDK5.0 的目录。
要启动 JConsole,运行 JDK_HOME/bin/jconsole 一个用于连接的对话框将会打开。对话框的 Local 标签列出了所有本地正在运行的 JVM,还包含进程的 ID 等信息。
Figure 2: Local Tab.
JConsole 可以以三种方式连接正在运行的 JVM:
- Local:使用 JConsole 连接一个正在本地系统运行的 JVM,并且执行程序的和运行 JConsole 的需要是同一个用户。JConsole 使用文件系统的授权通过 RMI 连接器连接到平台的 MBean 服务器上。这种从本地连接的监控能力只有 Sun 的 JDK 具有
- Remote:使用下面的 URL 通过 RMI 连接器连接到一个 JMX 代理:
service:jmx:rmi:///jndi/rmi://hostName:portNum/jmxrmi
hostName填入主机名称,portNum为 JMX 代理启动时指定的端口。JConsole 为建立连接,需要在环境变量中设置 mx.remote.credentials 来指定用户名和密码从而进行授权。
- Advanced:使用一个特殊的 URL 连接 JMX 代理。一般情况使用自己定制的连接器而不是 RMI 提供的连接器来连接 JMX 代理,或者是一个使用 JDK1.4 的实现了 JMX 和 JMX Rmote 的应用。
当 JConsole 成功建立连接,它从连接上的 JMX 代理处获取信息,并且以下面几个标签页呈现信息。
- Summary tab. 监控 JVM 和一些监控变量的信息。
- Memory tab. 内存使用信息
- Threads tab. 线程使用信息
- Classes tab. 类调用信息
- VM tab. JVM 的信息
- MBeans tab.所有 MBeans 的信息
MBeans tab 展示了所有以一般形式注册到 JVM 上的 MBeans。MBeans tab 允许你获取所有的平台信息,包括那些不能从其他标签页获取到的信息。注意,其他标签页上的一些信息也在 MBeans 这里显示。另外,你可以使用 MBeans 标签管理你自己的应用的 MBeans
使用 MBeans Tab 监控和管理 MBean
注册到 JMX 代理的平台或者应用的 MBeans,可以通过 MBeans 标签获取。例如, 内存的 MBeans 如下面定义
public interface MemoryMXBean {public MemoryUsage getHeapMemoryUsage();
public MemoryUsage getNonHeapMemoryUsage();
public int getObjectPendingFinalizationCount();
public boolean isVerbose();
public void setVerbose(boolean value);
public void gc();}
内存的 MBean 包括四个属性:
HeapMemoryUsage
. 用于描述当前堆内存使用情况的只读属性NonHeapMemoryUsage
. 用于描述当前的非堆内存的使用情况的只读属性ObjectPendingFinalizationCount
.用于描述有多少对象被挂起以便回收。Verbose
.用于动态设置 GC 是否跟着详细的堆栈信息,为一个布尔变量
内存的 MBean 支持一个操作——GC,此操作可以发送进行实时的垃圾回收请求。
Figure 3: MBeans Tab.
左边的树形结构以名字的方式展示了所有 MBeans 的列表。一个 MBean 对象的名字由一个域的名字和一串关键字属性组成。例如,JVM 的平台的 MBeans 是在“java.lang”域下的一组,而日志的 MBeans 则在 ”java.util.logging
“ 域下。MBean 对象的名字在 javax.management.ObjectName 规范中定义。
当你在树中选中一个 MBean,属性,方法,或者通知等一些信息会再右边显示出来。如果属性是可写的(属性被标志为蓝色),你可以进行设置。你可以操作在 Operations tab 中列出的操作。你也可以看到由 MBean 发送出来的通知:默认情况,如果你不订阅通知的话,JConsole 不会收到 MBean 发生过来的通知。你可以点击 "Subscribe
“(订阅) 按钮来堆通知进行定义,而使用 ”Unsubscribe
“ 按钮来取消订阅
Figure 4: MBeans Notification.
监控内存
内存标签页通过读取内存系统、内存池、垃圾回收的 MBean 来获取对内存消耗、内存池、垃圾回收的情况的统计。
图:
上图展示了内存随时间变化的使用情况。有对堆的、非堆的以及特殊内存池的统计。内存池信息是否能被获取,取决与使用的 Java 虚拟机。下面列表展示了 HotSpot 虚拟机的内存池情况。
Eden Space (heap): 内存最初从这个线程池分配给大部分对象。
Survivor Space (heap):用于保存在 eden space 内存池中经过垃圾回收后没有被回收的对象。
Tenured Generation (heap):用于保持已经在 survivor space 内存池中存在了一段时间的对象。
Permanent Generation (non-heap): 保存虚拟机自己的静态 (refective) 数据,例如类(class)和方法(method)对象。Java 虚拟机共享这些类数据。这个区域被分割为只读的和只写的,
Code Cache (non-heap):HotSpot Java 虚拟机包括一个用于编译和保存本地代码(native code)的内存,叫做“代码缓存区”(code cache)
详细信息区域给出一些当前线程的信息:
Used:已使用:当前的内存使用量。使用的内存包括所有对象(能被获取和不能被获取的)所占用的内存。
Committed:分配量:Java 虚拟机保证能够获取到的内存量。分配内存(committedmemory)的量可能随时间改变。Java 虚拟机可能释放部分这里的内存给系统,相应的分配的内存这时可能少于初始化时分配的给它的量。分配量总数大于或等于已使用的内存量。
Max :内存管理系统可以使用的最大内存量。这个值可以被改变或者不做设定。如果 JVM 试图增加使用的内存到大于分配量(committedmemory)的情况,内存分配可能失败,即便想使用的内存量小于或者等于最大值(如:系统虚拟内存比较低时)
Usage Threshold The usage threshold of a memory pool. This field will only beshown if the memory pool supports usage threshold.
GC time :垃圾回收使用的总时间和调用垃圾回收的次数。它可能有好几行,每行代表 JVM 使用的垃圾回收算法。(
右下角的棒状图表显示了被 JVM 的内存池消耗的内存。如果内存使用超过 usage threshold, 则棒会变红。usagethreshold 是用于支持内存检查的 Memory Pool MBean 的一个属性。MemoryPoolMXBean 定义了一系列方法用于检查内存。
public interface MemoryPoolMXBean {
….
// Usage threshold
public long getUsageThreshold();
public void setUsageThreshold(long threshold);
public boolean isUsageThresholdExceeded();
public boolean isUsageThresholdSupported();
// Collection usage threshold
public long getCollectionUsageThreshold();
public void setCollectionUsageThreshold(long threshold);
public boolean isCollectionUsageThresholdSupported();
public boolean isCollectionUsageThresholdExceeded();
}
每种内存池可能有两种内存初始话支持:usage threshold 和 collection usage threshold 特殊的内存池可能两种都不支持。
Usage Threshold
usage threshold是内存池中一个可管理的属性。它使用低负荷的内存监控。设置 usage threshold 为正值则 usage threshold 检查内存池。设置 usage threshold 为零,则关闭检查。默认值由 JVM 设置。JVM 一般让 usage threshold 在最合适的时候检查内存,典型的在 GC 的过程中和某些分配内存的时候。如果 JVM 发现当前的内存使用超过了 usage threshold, 它将会把 UsageThresholdExceeded
属性设置为 true
有些内存池可能不支持 usage threshold。 你可以使用 UsageThresholdSupported 属性来判断一个内存池是否支持
usage threshold。 例 如,一个比较完善(generational garbage collector)的垃圾回收器(如 HotSpot 的虚拟机),most of the objects are allocated in the young generation,从 eden 内存池中产生。eden pool 被设计成可以被装满;再 eden pool 中执行垃圾回收将会释放他
更多详情见请继续阅读下一页的精彩内容:http://www.linuxidc.com/Linux/2015-02/113417p2.htm
Figure 10: MBeans Tab Threading.
为检查你的应用是否进入死锁(例如, 你的应用挂起),你可以使用 findMonitorDeadlockedThreads
操作。
Figure 11: Find Deadlocked Threads.
一旦你选择了 findMonitorDeadlockedThreads
按钮,将会有一个弹出窗口显示结果。在上面例子中,JConsole 连接了一个存在 3 个死锁线程的示例应用 SampleTest。如上所示,检查出 ID 为 12,10 和 11 的线程死锁。想查询更多的线程信息,可以使用 getThreadInfo
操作。线程的 MBean 支持 getThreadInfo
操作的四种形式,
- 对一个给定的线程 ID,给出最深的堆栈情况
- 堆一系列的线程 ID,给出最深的堆栈情况
- Of a given thread ID with no stack trace.
- Of an array of thread IDs with no stack trace.
对应死锁情况,你一般会比较关系堆栈情况。你可以在 getThreadInfo 操作的第一个参数中输入死锁的线程 ID 和你想跟踪的堆栈深度。
Figure 12: ThreadInfo for Thread ID = 12.
双击 stackTrace 属性的值域将会显示一个复合对话框,你可以在堆栈中来回查看。图 13,14 显示了死锁线程 - 1 的复合对话框中的第一层堆栈和第二层堆栈。
Figure 13: Top Frame of the Stack Trace of DeadlockedThread-1.
Figure 14: Second Frame of the Stack Trace of DeadlockedThread-1.
线程标签页提供了一个友好的界面供查看线程的堆栈。你可以找到死锁线程的名字,使用getThreadInfo
查找线程信息。然后又可以使用线程标签页来分析死锁。
控制日志等级
Logging MBean 定义了 LoggerNames
属性,用于描述日志名称。为找到你的应用的日志,可以选择 在 MBeans 树中 java.util.logging
下的 Logging MBean,双击 LoggerNames 属性
Figure 15: List of All Logger Names.
Logging MBean 也支持三种操作:
getParentLoggerName
. 返回指定 logger 的父 loggergetLoggerLevel
. 返回指定 logger 的日志等级setLoggerLevel
. 设置指定 logger 到一个新的等级
所有三个操作都把日志名称作为第一个参数。
Figure 16: Setting Log Level.
获取操作系统资源信息 -Sun 平台下的扩展
JDK5.0 扩展了操作系统的 MBean,以此可以获取一下系统资源的信息,如:
- 处理的 CPU
- 总共的和空闲的物理内存
- 可获得的虚拟内存。(即保证可以分配给运行的进程的虚拟内存)
- 总共的和空闲的交换区
- 打开的文件总数(只能在 Unix 下使用)
当打开 MBeans 标签下的 Operating System MBean,你可以看到平台可以执行的所有属性和操作。你可以监控任何一个属性随时间的变化——如,CPU 时间 - 双击属性的值域部分。
Figure 17: MBeans Tab OS.
除此之外,VM 标签和 Summary 标签提供了操作系统资源的一些信息
管理应用的 MBean
被监控的 SampleTest 应用有它自己的 Hello MBean:
com.sun.example:type=Hello
如果 CacheSize 属性发生改变,Hello MBean 将会发送一个通知。你可以和管理平台的 MBeans 一样使用 MBeans 标签页来管理你的应用的 MBean。例如,当 CacheSize 属性变化的时候你想监控。你首先可以在
Notification 标签页中订阅。如果你改变 CacheSize,你可以看到一个通知被发送。
Figure 18: Notifications.
相关信息
- Monitoring and Management for the Java Platform
- Monitoring and Management Tools
JProfiler 试用手记
JProfiler 是一款 Java 的性能监控工具。可以查看当前应用的 对象、对象引用、内存、CPU 使用情况、线程、线程运行情况(阻塞、等待等),同时可以查找应用内存使用得热点,即:哪个对象占用的内存比较多;或者 CPU 热点,即:哪儿方法占用的较大得 CPU 资源。我使用的是 4.3.2 版本,以前试用过 3 ** 版本,不过那个 bug 比较多,容易死,4** 版本稳定多了。
有了上面那些信息对于系统的调优会有很大帮助。这几篇文章基本介绍了常见东西了,下面说点心得。
- JProfiler 监控是要消耗系统资源的,所以一般情况下不要用于性能测试时候的监控。
- 如果要用于相对大压力情况下,可以有选择的打开监控项,不用所有都打开。主要有两个,一个是内存监控,打开的情况下可以查找内存分配热点。一个是 CPU 监控,打开的情况下可以查看 CPU 使用热点。
如图所示,红笔标注部分。如果两个都关闭的话,还是可以跑一定压力的,同时还可以监控对象数量。 - 个 人认为最好用的(也是用的最多的)是查询当前的对象的数量。数量监控很重要,如果你使用了单例,那么你只会看到有一个对象存在,如果多了就说明程序有问题 了。同样,如果应用进行一系列操作,检查一下该销毁的对象是否还继续存在,如果没有释放,就得考虑是否存在内存溢出了。
- JProfiler 还提供了一个比较好的检查内存溢出得工具。他可以查找某个对象的引用情况,即:当你发现某个该释放掉的对象没有释放,就可以看一下哪个实例在引用它,找到了根即找到了溢出点。
具体操作如下:在“Memory Views”界面中右键选择你要监控的对象,选择第一项“Take Heap Snapshot for Selection”,选择完成后会进入“Heap Walker”界面,界面下面提供几个功能,选择“References”即可。如图: - JProfiler 提供不同的观察粒度,提供对类的监控、对包的监控、对 J2EE 组件的监控,同时过滤器也比较好用,直接定位你关注的包或类即可。
- JProfiler 的监控可能与应用之间存在一定时间差,所以有些时候需要等待刷新,才能显示正确系统情况。