javaagent,idea中对javaagent的运用

javaagent,idea中对javaagent的运用_第1张图片

 如上图所示,平时我们在IDEA中随便写一个类,写上一个测试方法,然后点那个三角符号就会成功运行,如下图:

javaagent,idea中对javaagent的运用_第2张图片

并且点击那个红色正方形按钮程序就会停止,这是怎么实现的呢?

经查看,程序运行界面有一行命令:

javaagent,idea中对javaagent的运用_第3张图片

把它复制下来,看下:

javaagent,idea中对javaagent的运用_第4张图片

好乱,整理下:

javaagent,idea中对javaagent的运用_第5张图片

显而易见,原来是调用了java.exe来运行com.dengbin.socket.TestThread这个类的main方法。

然而我们仔细观察一下这些命令,-classpath是指类查找路径、-D开头的是定义环境变量,那-javaagent是啥?

并且能发现,这个:

javaagent,idea中对javaagent的运用_第6张图片

这个文件名叫做idea_rt.jar,那是不是idea是通过这个jar包来管理我们上面在idea中运行的程序呢?

先看看-javaagent是啥东西,我们在命令行中输入:java -help看看:

javaagent,idea中对javaagent的运用_第7张图片

啥叫编程语言代理???好吧,先不管,先看看idea_rt.jar里是啥:

javaagent,idea中对javaagent的运用_第8张图片

javaagent,idea中对javaagent的运用_第9张图片

MANIFEST.MF中有一行:Premain-Class: com.intellij.rt.execution.application.AppMainV2$Agent

这个光看字面意思就知道,Premain,肯定是在main函数运行之前运行的东东

然后我们进com.intellij.rt.execution.application.AppMainV2$Agent看看:

javaagent,idea中对javaagent的运用_第10张图片

然后它是调用了

AppMainV2.premain(args);

跟踪进去看:

javaagent,idea中对javaagent的运用_第11张图片

留意一下打上红框的代码,58不是ascii码的冒号":"吗,再看一下命令行:

-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2019.1.3\lib\idea_rt.jar=52551:C:\Program Files\JetBrains\IntelliJ IDEA 2019.1.3\bin

可以分析出,这个int p = args.indexOf(58),就是要提取出idea_rt.jar=52551中的端口号52551

继续查看,进入到startMonitor函数:

javaagent,idea中对javaagent的运用_第12张图片

嗖嘎,原来是连接127.0.0.1:52551,然后无限等待接收命令啊!

既然是这样,那就写个程序试下:

写个socket服务端,绑定到端口58888:

package com.dengbin.socket.ideaagent;

import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

/**
 * Hello world!
 *
 */
public class IdeaAgent
{
    public static void main( String[] args ) throws IOException {
        if (args == null  || args.length<1 || args[0] == null){
            System.out.println("please input the port will start.");
            return ;
        }
        int port = Integer.parseInt(args[0]);
        System.out.println( "starting ideaagent at port:"+ port );

        ServerSocket serverSocket = new ServerSocket(port);
        System.out.println( "start succeed.");

        //监听
        System.out.println( "waiting for client connect.");
        Socket accept = serverSocket.accept();
        System.out.println( "one client is connected ["+ accept.getInetAddress() + ":" + accept.getPort() +"]");

        OutputStream outputStream = accept.getOutputStream();
        Scanner scanner = new Scanner(System.in);
        while (true)
        {
            //读取输入,给客户端输出命令
            System.out.println("please enter command: ");
            String s = scanner.nextLine();
            String message = s + "\n";
            outputStream.write(message.getBytes("US-ASCII"));
        }
    }
}

用maven打好包,在命令行跑起来:

javaagent,idea中对javaagent的运用_第13张图片

再启程一个我们刚开始写的程序,并且指定端口为58888:

javaagent,idea中对javaagent的运用_第14张图片

javaagent,idea中对javaagent的运用_第15张图片

此时,观察服务端也是监听到了一个客户端了:

javaagent,idea中对javaagent的运用_第16张图片

观察idea_rt.jar里面的代码com.intellij.rt.execution.application.AppMainV2#startMonitor:

javaagent,idea中对javaagent的运用_第17张图片

代码的意思是接收到字符:STOP就停止程序,是不是这样呢,我们试试:

javaagent,idea中对javaagent的运用_第18张图片

启动的程序还真停止了。

由此,得出了我们的疑问的答案:

idea在启动程序的时候指定-javaagent为idea_rt.jar,idea_rt.jar做的最重要的事是启动了一个socket连接到指定的服务器,然后开启了一个后台线程等待接收服务器的指定,当收到指令:STOP时,就调用代码

System.exit(1);

程序就停止了

 

看似很神秘的事,背后都并不神秘。

 

你可能感兴趣的:(IDEA,idea,idea_rt.jar,javaagent)