Sto*_*oud 7 java jvm classloader javaagents
基本上,我正在尝试编写一些列出JVM加载的每个类的东西.我写的是有效的,但它只适用于它运行的jvm.我精心设计了一个java代理来动态注入另一个JVM,但后来意识到我实际上并不知道如何注入它.我如何实际将此代理发送到另一个JVM?可能吗?
动态代理需要声明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进程上.
可以使用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.
据我从评论中了解到,您对可以从另一个 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 为其启动加载器的所有类,如果没有,则长度为零