Monitor Ctrl-Break 线程是啥

发布时间 2023-11-29 09:29:47作者: 沧海一滴

 

问题解决了,但是问题背后的问题,还没有得到解决:

Monitor Ctrl-Break 线程是啥?它是怎么来的?

我们先 jstack 一把看看线程堆栈呗。

而在 idea 里面,这里的“照相机”图标,就是 jstack 一样的功能。

 

 

我把程序恢复为最初的样子,然后把“照相机”就这么轻轻的一点:

 

从线程堆栈里面可以看到 Monitor Ctrl-Break 线程来自于这个地方:

com.intellij.rt.execution.application.AppMainV2$1.run(AppMainV2.java:64)

而这个地方,一看名称,是 idea 的源码了啊?

不属于我们的项目里面了,这咋个搞呢?

思考了一下,想到了一种可能,于是我决定用 jps 命令验证一下:

看到执行结果的时候我笑了,一切就说的通了。

果然,是用了 -javaagent 啊。

那么 javaagent 是什么?

好的,要问答好这个问题,就得另起一篇文章了,本文不讨论,先欠着。

只是简单的提一下。

你在命令行执行 java 命令,会输出一大串东西,其中就包含这个:

 

什么语言代理的,看不懂。

叫我们参阅 java.lang.instrument。

那它又是拿来干啥的?

简单的一句话解释就是:

使用 instrument 可以更加方便的使用字节码增强的技术,可以认为是一种 jvm 层面的截面。不需要对程序源代码进行任何侵入,就可以对其进行增强或者修改。总之,有点 AOP 内味。

-javaagent 命令后面需要紧跟一个 jar 包。

-javaagent:<jar 路径>[=<选项>]

instrument 机制要求,这个 jar 包必须有 MANIFEST.MF 文件,而 MANIFEST.MF 文件里面必须有 Premain-Class 这个东西。

所以,回到我们的程序中,看一下 javaagent 后面跟的包是什么。

在哪看呢?

就这个地方:

 

 

你把它点开,命令非常的长。但是我们关心的 -javaagent 就在最开始的地方:

 

 

 

 

 

 

 

此时此刻,我们距离真相,只有一步之遥了。

进到对应的包里,发现有三个 class 类:

 

 

 

 

 

我说过什么来着?

来,大声的跟我念一遍:源码之下无秘密。

Monitor Ctrl-Break 线程就是这里来的。

而仔细看一眼这里的代码,这个线程在干啥事呢?

Socket client = new Socket("127.0.0.1", portNumber);

啊,我的天呐,来看看这个可爱的小东西,socket 编程,太熟悉了,简直是梦回大学实验课的时候。

它是链接到 127.0.0.1 的某个端口上,然后 while(true) 死循环等待接收命令。

那么这个端口是哪个端口呢?

就是这里的 62325:

 

需要注意的是,这个端口并不是固定的,每次启动这个端口都会变化。

 

玩玩它


既然它是 Socket 编程,那么我就玩玩它呗。

先搞个程序:

public class SocketTest{
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(12345);
        System.out.println("等待客户端连接.");
        Socket socket = serverSocket.accept();
        System.out.println("有客户端连接上了 "+ socket.getInetAddress() + ":" + socket.getPort() +"");
 
        OutputStream outputStream = socket.getOutputStream();
        Scanner scanner = new Scanner(System.in);
        while (true)
        {
            System.out.println("请输入指令: ");
            String s = scanner.nextLine();
            String message = s + "\n";
            outputStream.write(message.getBytes("US-ASCII"));
        }
    }
}

我们把服务端的端口指定为了 12345。

客户端这边的端口也得指定为 12345,那怎么指定呢?

别想复杂了,简单的一比。

把这行日志粘贴出来:

 

需要说明的是,我这边为了演示效果,在程序里面加了一个 for 循环。

然后我们在这里把端口改为 12345:

 

 

把文件保存为 start.bat 文件,随便放一个地方。

万事俱备。

我们先把服务端运行起来:

 

在 cmd 窗口里面输出了我们的日志,说明程序正常运行。

而在服务端这边,显示有客户端连接成功。

叫我们输入指令。

输入啥指令呢?

看一下客户端支持哪些指令呗:

 

可以看到,支持 STOP 命令。

接受到该命令后,会退出程序。

来,搞一波,动图走起:

 

搞定。

好了,本文技术部分就到这里了,恭喜你知道了 idea 中的 Monitor Ctrl-Break 线程,这个学了没啥卵用的知识 。

如果要深挖的话,往 -javaagent 方向挖一挖。

应用很多的,比如耳熟能详的 Java 诊断工具 Arthas 就是基于 JavaAgent 做的。

有点意思。

 

https://developer.aliyun.com/article/901820