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

Yue*_*e S 1 java jvm

我试图通过设置 -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
Run Code Online (Sandbox Code Playgroud)

有没有办法通过在正在运行的 JVM 中设置一些选项来阻止这种行为?或者有什么可以解决的?

谢谢。

apa*_*gin 5

In general, this is not possible.

Serviceability Agent (sa-jdi) does not require cooperation from the target process. It just stops target JVM using ptrace syscall, and reads the memory of the process without JVM even knowing about that.

However, you can make debugging harder by overwriting the variables used by Serviceability Agent. Particularly, if you reset gHotSpotVMStructs global variable, SA will not be able to reconstruct internal VM structures, so that tools based on SA will stop working.

In order to do this, compile the following novmstructs.c program:

extern void *gHotSpotVMStructs;

int Agent_OnLoad(void *vm, char *options, void *reserved) {
    gHotSpotVMStructs = 0;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

How to compile:

gcc -fPIC -nostdlib -shared -olibnostructs.so -O2 nostructs.c
Run Code Online (Sandbox Code Playgroud)

Then run your Java application with the produced library attached as the agent:

java -agentpath:/path/to/libnostructs.so ...
Run Code Online (Sandbox Code Playgroud)

The next time someone tries to invoke ClassDump or other SA-based utility, the exception will occur:

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
Run Code Online (Sandbox Code Playgroud)