Reputation: 76
So I'm creating a profiler application. It has a GUI class which is used to control the profiler. It consists of 2 pieces at runtime: 1) An application (GUI) for control 2) An agent to be loaded into the target application
It lists out PIDs, and then calls loadAgent() on the VM. So I want all of the logic to be done in the primary application. The idea I had was to get an instance of the Instrumentation class from my agent, then invoke a callback method via reflection. This would set a static field in the primary application to the Instrumentation instance, and notify the primary application that the agent is successfully loaded.
The issue I'm having is that I'm unable to grab the primary application's class which contains the Instrumentation field. Class.forName(String) implicitly looks in the ClassLoader for that application. The other method can look for classes in another ClassLoader...unfortunately I have been entirely unable to get the ClassLoader for the agent/target application from the primary application to pass into it!
I see no methods in the Instrumentation or VirtualMachine classes that allow me to do this. I haven't found any questions of this nature on the internet that are answered in a satisfactory method either.
I had some ideas... A) If there is some kind of equivalent of Class.forName for ClassLoaders maybe I could serialize the ClassLoader and send the serialized string over a socket, then grab it that way. Thus far I haven't found anything remotely like this. B) Navigate through the ClassLoaders in the agent (there is a ClassLoader.getParent() method..but that's the only means of navigation I see), and find the proper ClassLoader with a deep equals comparison. I don't even know where to begin..I was hoping I could iterate through VirtualMachines.list() and there would be something I could call. There isn't. C) Load the agent in the primary application, and somehow pass that specific instance of the agent to the target application. Since they are different ClassLoaders I can only assume this doesn't work. For all I know there may be a way to do it though? D) Create a custom ClassLoader in the primary application and load the target application using that. The issue here is I want full "attach" functionality which this prevents.
I really don't want to put all the logic in the agent, so I thought I would ask you guys before going that route. Googling this has been less than fruitful. Thanks in advance!
Upvotes: 0
Views: 47
Reputation: 44087
I think that you misunderstand how the attach API works in this case. The attach API allows to register an agent from a local VM process to a remote JVM process. After attachment, the remote VM executes the agent's agentmain
method in a designated thread. The agent is not aware of its attachment process and cannot communicate objects from the remote heap to the attaching VM's heap.
Also, ClassLoader
s are not normally serializable. You would rather need to communicate necessary information via some socket between processes. For this purpose, the local VM can for example communicate a socket address as an argument to the agent on which the local process later waits for information to arrive from the remote VM. In this cause, you should also consider what information you want to be exposed from the remote VM. You probably do not want to send serializable objects.
Upvotes: 2