问题
I'm trying to protect my classes in a running JVM by setting -XX:+DisableAttachMechanism.
However, I found that the process prevents tools like jconsole to attach, but still I can use following command the dump all the loaded classes in that 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
Is there any way to stop this behavior by setting some options in the running JVM? Or anything to work around?
Thanks.
回答1:
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;
}
How to compile:
gcc -fPIC -nostdlib -shared -olibnostructs.so -O2 nostructs.c
Then run your Java application with the produced library attached as the agent:
java -agentpath:/path/to/libnostructs.so ...
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
来源:https://stackoverflow.com/questions/48056863/disable-classdump-to-a-running-jvm-process-by-using-sa-jli