使用sa-jli禁用对正在运行的JVM进程的ClassDump

zz2j4svz  于 2023-05-17  发布在  其他
关注(0)|答案(2)|浏览(145)

我试图通过设置-XX:+DisableAttachMechanism来保护正在运行的JVM中的类。
然而,我发现这个过程阻止了像jconsole这样的工具附加,但我仍然可以使用以下命令转储JVM中所有加载的类:

java -Dsun.jvm.hotspot.tools.jcore.PackageNameFilter.pkgList=com.xxxx -classpath ".:./bin:$JAVA_HOME/lib/sa-jdi.jar" sun.jvm.hotspot.tools.jcore.ClassDump 1234

有没有办法通过在运行的JVM中设置一些选项来停止这种行为?或者其他什么工作?
谢谢

rbl8hiat

rbl8hiat1#

一般来说,这是不可能的。
Serviceability Agent(sa-jdi)不需要来自目标进程的协作。它只是使用ptrace syscall停止目标JVM,并在JVM甚至不知道的情况下读取进程的内存。
但是,通过覆盖Serviceability Agent使用的变量,可以使调试更加困难。特别是,如果重置gHotSpotVMStructs全局变量,SA将无法重建内部VM结构,因此基于SA的工具将停止工作。
为此,请编译以下novmstructs.c程序:

extern void *gHotSpotVMStructs;

int Agent_OnLoad(void *vm, char *options, void *reserved) {
    gHotSpotVMStructs = 0;
    return 0;
}

如何编译:

gcc -fPIC -nostdlib -shared -olibnostructs.so -O2 nostructs.c

然后运行Java应用程序,并将生成的库附加为代理:

java -agentpath:/path/to/libnostructs.so ...

下次有人尝试调用ClassDump或其他基于SA的实用程序时,将发生异常:

Attaching to process ID 574, please wait...
Exception in thread "main" java.lang.reflect.InvocationTargetException
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at sun.tools.jstack.JStack.runJStackTool(JStack.java:140)
        at sun.tools.jstack.JStack.main(JStack.java:106)
Caused by: java.lang.RuntimeException: gHotSpotVMStructs was not initialized properly in the remote process; can not continue
        at sun.jvm.hotspot.HotSpotTypeDataBase.readVMStructs(HotSpotTypeDataBase.java:418)
        at sun.jvm.hotspot.HotSpotTypeDataBase.<init>(HotSpotTypeDataBase.java:91)
        at sun.jvm.hotspot.HotSpotAgent.setupVM(HotSpotAgent.java:395)
        at sun.jvm.hotspot.HotSpotAgent.go(HotSpotAgent.java:305)
        at sun.jvm.hotspot.HotSpotAgent.attach(HotSpotAgent.java:140)
        at sun.jvm.hotspot.tools.Tool.start(Tool.java:185)
        at sun.jvm.hotspot.tools.Tool.execute(Tool.java:118)
        at sun.jvm.hotspot.tools.JStack.main(JStack.java:92)
        ... 6 more
iq0todco

iq0todco2#

老问题了但我们开始了

Field jvmField = ManagementFactory.getRuntimeMXBean().getClass().getDeclaredField("jvm");
jvmField.setAccessible(true);
VMManagement jvmInstance = (VMManagement) jvmField.get(ManagementFactory.getRuntimeMXBean());
List<String> jvmArguments = jvmInstance.getVmArguments();

jvmArguments将拥有启动jvm的所有参数,你可以在加载实际的类之前检查这些参数,如果使用了一个标志,你不想中止加载。
但请记住,这只是从jvm转储类的许多方法之一,你可以附加一个代理,钩子ClassLoader#defineClass和许多其他东西,只要你在jvm中,就没有办法100%“转储证明”。

相关问题