Starting a Java agent after program start
Asked Answered
R

4

28

Is it possible to insert a javaagent after virtual machine start from within the same VM?

Lets say for example we have an agent in a jar myagent.jar with the appropriate meta data set-up and an agentmain method already implemented. Now the users program calls an API call which should result in the insertion of the agent so that it can redefine the classes.

Can it be done and how?

Rabbitfish answered 14/8, 2009 at 10:46 Comment(0)
E
20

https://web.archive.org/web/20141014195801/http://dhruba.name/2010/02/07/creation-dynamic-loading-and-instrumentation-with-javaagents/ has a great example of how to write an agent as well as how to start one on the fly.

Easternmost answered 18/12, 2010 at 4:4 Comment(6)
It's not meant to be a self contained tutorial, true. But it is a great example for advanced Java developers. I, personally, had no problem with the example.Easternmost
The link is broken. I was able to find it archived on the WayBackMachine: web.archive.org/web/20141014195801/http://dhruba.name/2010/02/…Package
that link does not work anymore. you should have copied content and pasted here.Denary
The wayback link should sufficeEasternmost
@AlanCabrera I'm using jdk 1.8. I have tried oracle and openjdk, but I never can attach to the jvm. The attempt causes a threaddump in the target jvm and fails on the injecting jvm saying com.sun.tools.attach.AttachNotSupportedException: Unable to open socket file: target process not responding or HotSpot VM not loaded at sun.tools.attach.LinuxVirtualMachine.<init>(LinuxVirtualMachine.java:106) at sun.tools.attach.LinuxAttachProvider.attachVirtualMachine(LinuxAttachProvider.java:63) at com.sun.tools.attach.VirtualMachine.attach(VirtualMachine.java:208) at Main.main(Main.java:15)Ingrowth
I have tried this on CentOS and Ubuntu. Both failed the same wayIngrowth
P
15

Yes, you just have to pass the JVM process ID to the VirtualMachine.attach(String pid) method, and load the agent jar. The VirtualMachine class is available in the JDK_HOME/lib/tools.jar file. Here's an example of how I activate an agent at runtime:

public static void attachGivenAgentToThisVM(String pathToAgentJar) {
  try {                                                                               
    String nameOfRunningVM = ManagementFactory.getRuntimeMXBean().getName();                                                   
    String pid = nameOfRunningVM.substring(0, nameOfRunningVM.indexOf('@'));                                                   
    VirtualMachine vm = VirtualMachine.attach(pid);                                                                            
    vm.loadAgent(pathToAgentJar, "");
    vm.detach();   
  } catch (Exception e) {
    e.printStackTrace();
  }
}                                                                                                            
Package answered 30/10, 2014 at 20:24 Comment(5)
thanks for good answer. but when i am trying the same but i got an exception ** com.sun.tools.attach.AgentLoadException: Agent JAR not found or no Agent-Class attribute **Hallucinogen
I suspect it's a dependency issue, here how to solve in maven: m.blog.csdn.net/blog/chendeng8899/8487336 ("Dynamic loading of a javaagent at runtime" section)Discretionary
@Package I'm using jdk 1.8. I have tried oracle and openjdk, but I never can attach to the jvm. The attempt causes a threaddump in the target jvm and fails on the injecting jvm saying com.sun.tools.attach.AttachNotSupportedException: Unable to open socket file: target process not responding or HotSpot VM not loaded at sun.tools.attach.LinuxVirtualMachine.<init>(LinuxVirtualMachine.java:106) at sun.tools.attach.LinuxAttachProvider.attachVirtualMachine(LinuxAttachProvider.java:63) at com.sun.tools.attach.VirtualMachine.attach(VirtualMachine.java:208) at Main.main(Main.java:15)Ingrowth
I have tried this on CentOS and Ubuntu. Both failed the same wayIngrowth
It needs tools.jar, is it worth adding tools.jar in class path. (using Java8)Perretta
H
4

You should be able to do it in Java 6, see the package documentation chapter "Starting Agents After VM Startup"

edit: Maybe it was possible in Java 5 already and just the javadocs didn't mention it that explicitly

Haydenhaydn answered 14/8, 2009 at 11:1 Comment(3)
It does not specify what the method call is however. Looking further into it however would ((URLClassLoader)ClassLoader.getSystemClassLoader()).addURL(....) where the URL added pointed to the myagent.jar result in the agentmain being called?Rabbitfish
Is this Java 6 in general or only with HotSpot?Itu
@Paul: I haven't tried it so I can't say if it works like that but it seems reasonable. However you will have to call addURL by reflection since it is protected. Something like: URLClassLoader sysloader = (URLClassLoader)ClassLoader.getSystemClassLoader(); Class sysclass = URLClassLoader.class; try { Method method = sysclass.getDeclaredMethod("addURL",parameters); method.setAccessible(true); method.invoke(sysloader,new Object[]{ yourURL }); }Haydenhaydn
B
1

Having encountered the same issue, I have found a far more comprehensive solution, from the ByteBuddy library.

ByteBuddy thoroughly attempts to load its java agent dynamically:

Installs an agent on the currently running Java virtual machine. Unfortunately, this does not always work. The runtime installation of a Java agent is supported for:

  • JVM version 9+: For Java VM of at least version 9, the attachment API was moved into a module and the runtime installation is possible if the {@code jdk.attach} module is available to Byte Buddy which is typically only available for VMs shipped with a JDK.
  • OpenJDK / Oracle JDK / IBM J9 versions 8-: The installation for HotSpot is only possible when bundled with a JDK and requires a {@code tools.jar} bundled with the VM which is typically only available for JDK-versions of the JVM.
  • When running Linux and including the optional junixsocket-native-common dependency, Byte Buddy emulates a Unix socket connection to attach to the target VM.
  • Bish answered 2/9, 2020 at 1:33 Comment(0)

    © 2022 - 2024 — McMap. All rights reserved.