性能文章>JConsole 里的 GC 按钮。>

JConsole 里的 GC 按钮。原创

https://a.perfma.net/img/2382850
3周前
175403

是这样的,前几天有个小伙伴给我发了段代码:

public class Main {

    static class OOMObject{
        public byte[] placeholder=new byte[64*1024];
    }

    public static void fillHeap(int num) throws InterruptedException {
        List<OOMObject> list = new ArrayList<>();
        for (int i = 0; i < num; i++) {
            //稍作延迟,令监视曲线的变化更加明显
            Thread.sleep(50);
            list.add(new OOMObject());
        }
        System.gc();
    }
    public static void main(String[] args) throws InterruptedException {
        fillHeap(1000);
    }
}

我看了一眼:问发生肾么事儿了?

他给我说:

歪歪,这个代码是我看书上演示 JConsole 检测内存的测试案例。但是我观察的时候看到了这里有个[执行GC]的按钮,手贱点了一下。我就想问一下这里的[执行GC]和代码里面的 System.gc() 是一回事吗?

我一看:嚯,好家伙,这问题有点意思啊。这我还真不知道呢。

于是我给他说:

这不,很快啊,我就研究完了。

先说结论:

JConsole 里面点击按钮执行 GC 和在程序里面调用 System.gc() 是一回事。

研究过程

从哪里开始研究呢?

来,一起说一遍:源码之下无秘密。

你知道的,JConsole 这画风一看就是 Java 用 swing 编程写出来的玩意。

好巧不巧,我大学的时候学 swing 学的风生水起,因为我太喜欢那种运行起来就能直接看到画面的感觉了。

对于初学者是一种鼓励的感觉。

那么就很简单了,我只要找到 JConsole 对应的源码,看看点击 GC 按钮的时候它执行的源码是什么不就完事了吗?

那么问题来了,JConsole 的源码去哪里找呢?

OpenJDK 里面就有:

http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/758db1c4c65c/

把下载下来的源码导入到 Idea 里面,然后全局查找 JConsole 类:

可以看到在源码中的路径为:

sun.tools.jconsole.JConsole

这里还有我们熟悉的 javac、jcmd、jinfo、jmap、jps、jstack、jstat 这些小工具。

找到 JConsole 的源码之后怎么办呢?

读呗。

但是我大概读了 5 分钟的样子,感觉不对劲。

swing 编程我基本上已经全部还给老师了,看着有点懵逼的样子,只能连蒙带猜的看个大概,效率太低了。

但是我看的时候看到这行代码的时候,我突然冒出了另外一个思路:

你说这行是在干啥?

用脚指头猜也知道是设置 title。

title 是什么?

诶,不就是 JConsole 页面的这个玩意吗?

这一点我还是没还给老师的。

在源码里面 title 值是从这里取出来的:

title = Messages.JAVA_MONITORING___MANAGEMENT_CONSOLE;

这是个啥东西?

我也不知道,反正我二话不说上去就是一个全局搜索,路子就是这么野:

这一看,嚯,这不是多个配置文件嘛,整的还是国际化。

那一串看着像是乱码的玩意,很明显,是 Unicode 嘛,来转义一波:

你说这事整的,还真被我猜对了。

验证了这个点,接下来的思路就很简单了。

这不是还有[执行]两个字的中文嘛?

执行对应的 Unicode 是 \u6267\u884c 。

你懂我意思吧?

上来就是一个反向操作,回手掏:

PERFORM_GC=\u6267\u884c &GC

仅有的那点 swing 编程知识告诉我,接下来只要找 PERFORM_GC 对应的文案是在哪里用的,不就能拿到这个 button 了吗?

屁话少说,直接上来又是一个全局搜索:

看到这行代码的时候我觉得我真特么的是一个及里日。

及里儿斯就是 genius,天才的意思。

来,看一眼这行代码:

这个按钮的变量的名称就是 gcButton。

而当我看到这个 gcButton 位于的 Java 类的时候,我才发现我大意了:

sun.tools.jconsole.MemoryTab

MemoryTab,内存选项卡,多贴切啊,简直就是见名知意了。

而这两个类隔的并不远,我要是把类名看一眼,也不至于这样反向去查:

这波看起来是走远了一点,但是不亏,反正就是找到了 gcButton。

最终看一眼 gcButton 被调用的地方:

真相就是一步之遥了。

这代码对应的 gc() 方法是啥呢?

proxyClient.getMemoryMXBean().gc();

首先它要获取一个 MemoryMXBean 出来,然后调用它的 gc 方法:

而 MemoryMXBean 是一个接口,它对应的实现类是:

sun.management.MemoryImpl

到这里了,就真相大白了。

这里的 gc() 方法和 System.gc() 一模一样:

所以,再次说一下结论:

JConsole 里面点击按钮执行 GC 和在程序里面调用 System.gc() 是一回事。

我承认,整个查找的过程中除了我的“及里儿斯”之外,还有一点运气的成分在里面。

诶,但是最终我就是找到了,你说这事搞的简直没地儿说理去。

分类:
标签:
请先登录,再评论

暂无回复,快来写下第一个回复吧~

为你推荐

字符串字面量长度是有限制的
前言 偶然在一次单元测试中写了一个非常长的字符串字面量。 正文 在一次单元测试中,我写了一个很长的字符串字面量,大概10万个字符左右,编译时,编译器给出了异常告警 `java: constant
多次字符串相加一定要用StringBuilder而不用-吗?
今天在写一个读取Java class File并进行分析的Demo时,偶然发现了下面这个场景(基于oracle jdk 1.8.0_144): ``` package test; public c
如何通过反射获得方法的真实参数名(以及扩展研究)
前段时间,在做一个小的工程时,遇到了需要通过反射获得方法真实参数名的场景,在这里我遇到了一些小小的问题,后来在部门老大的指导下,我解决了这个问题。通过解决这个问题,附带着我了解到了很多新的知识,我觉得
高吞吐、低延迟 Java 应用的 GC 优化实践
本篇原文作者是 LinkedIn 的 Swapnil Ghike,这篇文章讲述了 LinkedIn 的 Feed 产品的 GC 优化过程,虽然文章写作于 April 8, 2014,但其中的很多内容和
「每日五分钟,玩转 JVM」:久识你名,初居我心
聊聊 JVMJVM,一个熟悉又陌生的名词,从认识Java的第一天起,我们就会听到这个名字,在参加工作的前一两年,面试的时候还会经常被问到JDK,JRE,JVM这三者的区别。JVM可以说和我们是老朋友了
据说99.99%的人都会答错的类加载的问题
概述首先还是把问题抛给大家,这个问题也是我厂同学在做一个性能分析产品的时候碰到的一个问题。 同一个类加载器对象是否可以加载同一个类文件多次并且得到多个Class对象而都可以被java层使用吗请仔细注意
Java多线程——并发测试
编写并发程序时候,可以采取和串行程序相同的编程方式。唯一的难点在于,并发程序存在不确定性,这种不确定性会令程序出错的地方远比串行程序多,出现的方式也没有固定规则。那么如何在测试中,尽可能的暴露出这些问
Java多线程知识小抄集(一)
本文主要整理笔者遇到的Java多线程的相关知识点,适合速记,故命名为“小抄集”。本文没有特别重点,每一项针对一个多线程知识做一个概要性总结,也有一些会带一点例子,习题方便理解和记忆。 1.interr