Java - 将java代理注入到运行jvm中

Sto*_*oud 7 java jvm classloader javaagents

基本上,我正在尝试编写一些列出JVM加载的每个类的东西.我写的是有效的,但它只适用于它运行的jvm.我精心设计了一个java代理来动态注入另一个JVM,但后来意识到我实际上并不知道如何注入它.我如何实际将此代理发送到另一个JVM?可能吗?

Raf*_*ter 9

动态代理需要声明agentmain(String, Instrumentation)在目标VM中附加时执行的方法.您可以使用tools.jar依赖项,它(仅限Java 9)仅包含在JDK中,但不包含在JRE中.但是,您可以将代理程序与JDK捆绑在一起,并从那里附加到JVM.

最大的问题是不同的虚拟机API有所不同; 但是,你可以使用像byte-buddy-agent这样的库,它包含不同虚拟机的不同实现.附件将通过以下方式完成:

ByteBuddyAgent.attach("my.jar", "my-pid");
Run Code Online (Sandbox Code Playgroud)

会将my.jar中包含的代理程序附加到具有id my-id的Java进程上.


apa*_*gin 7

可以使用HotSpot Attach API注入代理.在类路径上
运行以下代码段$JAVA_HOME/lib/tools.jar.

    VirtualMachine vm = VirtualMachine.attach(PID);
    try {
        vm.loadAgent(agentJar);
    } finally {
        vm.detach();
    }
Run Code Online (Sandbox Code Playgroud)

或者,您可以使用我的命令行jattach实用程序执行此操作:

$ jattach PID load instrument false /path/to/agent.jar
Run Code Online (Sandbox Code Playgroud)

请注意,为了支持动态附加,您的Java代理应该具有agentmain方法和Agent-Class属性MANIFEST.MF.


apa*_*gin 5

据我从评论中了解到,您对可以从另一个 Java 进程中检查远程 JVM 的东西感兴趣。如果是这种情况,那么您需要可服务性代理而不是 Java 代理。

Serviceability Agent API允许您附加到另一个 JVM 进程、读取其内存、重建 VM 结构以及以类似反射的方式检查远程对象。

下面是一个示例工具,用于列出远程 JVM 加载的所有类:

import sun.jvm.hotspot.runtime.VM;
import sun.jvm.hotspot.tools.Tool;

public class ListRemoteClasses extends Tool {

    public static void main(String[] args) {
        new ListRemoteClasses().execute(args);
    }

    @Override
    public void run() {
        VM.getVM().getSystemDictionary().classesDo(klass -> {
            String className = klass.getName().asString().replace('/', '.');
            System.out.println(className);
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

如何运行它:

java -cp $JAVA_HOME/lib/sa-jdi.jar:. ListRemoteClasses PID
Run Code Online (Sandbox Code Playgroud)


Ram*_*asi -1

如果不查看您编写的内容,很难提供帮助,但这只是为了通知包public interface Instrumentation中有一个名为 Instrumentation 接口 ( )的类java.lang.instrument,它提供检测 Java 编程语言代码所需的服务。

该类提供的一种方法是getInitiatedClasses返回一个包含所有已加载类的数组。

查看此处的文档

获取启动类

Class[] getInitiatedClasses(ClassLoader loader)
返回 loader 为其启动加载程序的所有类的数组。如果提供的加载器为空,则返回由引导类加载器启动的类。

参数: loader - 将返回其启动类列表的加载器 返回 一个数组,其中包含 loader 为其启动加载器的所有类,如果没有,则长度为零