就这?一个没啥卵用的知识点.

why技术

共 2671字,需浏览 6分钟

 ·

2021-06-12 17:54

你好呀,我是whywhy。

嗯,是读者叫我歪歪的。

6c56fc6f59df56aa63d888a7a87a399d.webp

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

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() 是一回事吗?

f16572eb39b459dd004e9bc5f5c9a92f.webp

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

于是我给他说:

636b0c0f82c0a40c6b2292203466819e.webp

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

先说结论:

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

研究过程

从哪里开始研究呢?

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

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

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

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

a6c86390ef3e6596596a0c7c928f8033.webp

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

aa858e4ba233e9cb2eca8e91b741c78e.webp

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

OpenJDK 里面就有:

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

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

51fd3afbdbf8aad22d94b78a753afa7c.webp

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

sun.tools.jconsole.JConsole

45fb01f3031b0a6090a147a1ef326e76.webp

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

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

读呗。

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

e69ab6138f5e2700629e796a98e2c93a.webp

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

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

6d3e537f8b981ff27a1619df15f89e46.webp

你说这行是在干啥?

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

title 是什么?

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

697a68c1b1e440970d0d1e07f903eb4d.webp

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

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

title = Messages.JAVA_MONITORING___MANAGEMENT_CONSOLE;

这是个啥东西?

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

4d65823b244b6cc7dcad9195798f36ae.webp

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

6016ec813451bc18dfe47b6b8dac97d7.webp

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

69a1f0cdfe0d8f00987b09a221ae1454.webp

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

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

19e16c7aa084c9b978b0847db6bbb9e6.webp

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

6ef69f32bfaf97ee98b7fc619a4777c0.webp

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

你懂我意思吧?

6c23cd6e0afa2642a5ce036d0f35741b.webp

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

5b1dfaf3f1b7a9b22f2654398136fdf9.webp

PERFORM_GC=\u6267\u884c &GC

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

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

6b6827fc1ffb7bb738b35b1ac5fcfa4d.webp

看到这行代码的时候我觉得我真特么的是一个鸡里儿斯

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

bab97afd9a94a288f3f0b095c528186a.webp

来,看一眼这行代码:

4cc5e4f410962f5634cfa8fab672a426.webp

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

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

sun.tools.jconsole.MemoryTab

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

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

988cfff5571570a3611c725fab5499ed.webp

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

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

dfab70b7d9a2a210d612651463dc2eaa.webp

真相就是一步之遥了。

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

proxyClient.getMemoryMXBean().gc();

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

3f8fcf19fdbcf478d86562db611b3d65.webp

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

sun.management.MemoryImpl

056b42452d0a64a2ffba2b75d22d905d.webp

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

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

e59689c7c987492353fc8d5a0d3928f7.webp

所以,再次说一下结论:

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

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

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

那你看完了,我问你一个问题:

你觉得你知道了这个点,有什么卵用吗?

是的,没有。

那么恭喜你,又在我这里学到了一个没有任何卵用的知识点。

9047e23af649c6a5d80a9c29597772a9.webp

好了,就这样,明天端午了。

大家端午安康。

你看,我都祝你端午安康了,你给我安排一个“一键三连”问题不大吧?

8127226bbfebe7fb047333f3d0c4d41c.webp



推荐👍 :我不服!这开源项目居然才888个星!

推荐👍 :曝光一个网站,我周末就耗在上面了。推荐👍 :面试官:啥是请求重发啊?
推荐👍 :曾趟过微服务这条河,暗潮汹涌。
推荐👍 :414天前,我以为这是编程玄学...我是 why,一个主要写代码,经常写文章,偶尔拍视频的程序猿。欢迎关注我呀。
浏览 35
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报