Unloading a JVMTI agent at runtime?
Asked Answered
H

2

10

I'm using the attach API to load a JVMTI agent at runtime. I'd like to unload the JVMTI agent when my program is done without terminating the JVM the agent is loaded in. According to this documentation there is no way to do this from the attach API. Are there any other ways to force an agent to unload its self either through a Java API or from within the JVMTI agent?

Hodge answered 25/5, 2011 at 13:0 Comment(1)
This doesn't mean to be a proper answer, but just a suggestion. I've had a similar problem with JNI (I wanted to unload a module). The best solution I've found is simple as that: spawn a new JVM instance doing the work with the module, wait for it to terminate, and then when it's terminated, then the module is obviously unloaded. I bet you'll end doing this, after struggling for a while. I suggest you to skip the 'struggle' phase :PRepurchase
A
6

JVMTI spec says unloading (without JVM termination) is possible, but platform-dependent and out of specification's scope.

Asbestosis answered 5/6, 2011 at 9:59 Comment(0)
B
0

You have to load JVMTI agent programatically :

// attach to target VM
VirtualMachine vm = VirtualMachine.attach("2177");

// get system properties in target VM
Properties props = vm.getSystemProperties();

// construct path to management agent
String home = props.getProperty("java.home");
String agent = home + File.separator + "lib" + File.separator 
    + "your-agent-example.jar";

// load agent into target VM
vm.loadAgent(agent, "com.sun.management.jmxremote.port=5000");

// detach
vm.detach();

see doc here

After that you have to use a different classLoad than default :

You have to set the system property "java.system.class.loader" to be the name of your custom class loader for your target JVM.

see doc here

"Java's builtin Class loaders always checks if a class is already loaded before loading it. Reloading the class is therefore not possible using Java's builtin class loaders. To reload a class you will have to implement your own ClassLoader subclass."

In your case you have to implement a ClassLoader which has ClassLoader.getSystemClassLoader() has parent.

"Even with a custom subclass of ClassLoader you have a challenge. Every loaded class needs to be linked. This is done using the ClassLoader.resolve() method. This method is final, and thus cannot be overridden in your ClassLoader subclass. The resolve() method will not allow any given ClassLoader instance to link the same class twice. Therefore, everytime you want to reload a class you must use a new instance of your ClassLoader subclass. This is not impossible, but necessary to know when designing for class reloading."

see Dynamic Class Reloading

Burglarious answered 6/6, 2011 at 16:23 Comment(4)
This does not help with JVMTI agents which are native code. Detaching from the JVM doesn't cause the JVMTI agent to be unloaded.Hodge
I dont say that. The code example is just here to show how to load the agent. Unloading agent from the JVM is the same problem that unloading classes. The only solution is to use your own Class loader.Burglarious
If you look at the attach doc it clearly states that loadAgent is used to load agents that are written in Java while loadAgentLibrary and loadAgentPath are used to load JVMTI agents that are native code. Since the JVMTI agents are native code and not Java classes your discussion of class loaders does not apply. See download.oracle.com/javase/6/docs/jdk/api/attach/spec/…Hodge
i agree now, my solution is only for java agent.Burglarious

© 2022 - 2024 — McMap. All rights reserved.