diff --git a/README.md b/README.md index dbc6ec3..30a8631 100644 --- a/README.md +++ b/README.md @@ -100,6 +100,31 @@ methodWithArgs TraceAgent (trace_retval): `public int net.test.TestClass2nd.methodWithArgs(java.lang.String,int) returns with 12 ``` +## Attaching Agent to running java process (hotswap) + +The agent can be attached to already running java process. + +To start trace on a running process one can use: + +``` +$ java -cp /lib/tools.jar:target/trace-agent-1.0-SNAPSHOT.jar net.test.AgentLoader target/trace-agent-1.0-SNAPSHOT.jar + +The above command attaches to the running java process and installs the actions. The instrumentaion messages will start showing in the processes logs/stdout as per the configuration. + +For example when attaching to a Spark executor using its pid: +... +21/03/17 13:30:52 INFO yarn.Client: Application report for application_1614936955492_0466 (state: ACCEPTED) +TraceAgent is initializing +TraceAgent tries to install actions: [{actionId='trace_args', classMatcher='REGEXP(org\.apache\.spark\.sql\.execution\.SparkStratgies.*)'}, ...] +TraceAgent installed actions successfully +... +21/03/17 14:18:33 INFO yarn.Client: Application report for application_1614936955492_0470 (state: RUNNING) +21/03/17 14:18:34 INFO util.Utils: Using initial executors = 0, max of spark.dynamicAllocation.initialExecutors, spark.dynamicAllocation.minExecutors and spark.executor.instances +TraceAgent (timing): `public final void org.apache.spark.SparkContext$$anonfun$23.apply(org.apache.spark.ExecutorAllocationManager)` took 22 ms +TraceAgent (timing): `public final void org.apache.spark.SparkContext$$anonfun$24.apply(org.apache.spark.ContextCleaner)` took 2 ms +.... + +``` ## The config format @@ -230,6 +255,7 @@ In this case all the rules are used from both the internal and external action f In distributed environment when external action file is used you should take care on each node the action file is really can be accessed using the path. Otherwise the error is logged but the application continues: "TraceAgent does not find the external action file: ". + # The counter action This action can be used to count the number of of method calls. It has one parameter `count_frequency` which specifies after how many calls there will be a printout. diff --git a/pom.xml b/pom.xml index 7662074..092ada7 100644 --- a/pom.xml +++ b/pom.xml @@ -15,6 +15,8 @@ 1.8 1.8 net.test.TraceAgent + 1.8 + 1.8.0 @@ -29,6 +31,13 @@ byte-buddy 1.10.10 + + com.sun + tools + ${sun.tools.version} + system + ${java.home}/../lib/tools.jar + diff --git a/src/main/java/net/test/AgentLoader.java b/src/main/java/net/test/AgentLoader.java new file mode 100644 index 0000000..a7e20c9 --- /dev/null +++ b/src/main/java/net/test/AgentLoader.java @@ -0,0 +1,26 @@ +package net.test; + +import com.sun.tools.attach.VirtualMachine; + +import java.io.File; +import java.util.Optional; + +/** Agent Loader to attach to a PID. */ +public class AgentLoader { + + public static void main(String[] args) { + File agentFile = new File(args[0]); + + System.out.println(agentFile.getAbsolutePath()); + try { + String pid = args[1]; + System.out.println("Attaching to target JVM with PID: " + pid); + VirtualMachine jvm = VirtualMachine.attach(pid); + jvm.loadAgent(agentFile.getAbsolutePath()); + jvm.detach(); + System.out.println("Succefully attached to target JVM and loaded Java agent"); + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} diff --git a/src/main/java/net/test/TraceAgent.java b/src/main/java/net/test/TraceAgent.java index d361366..008f0d2 100644 --- a/src/main/java/net/test/TraceAgent.java +++ b/src/main/java/net/test/TraceAgent.java @@ -79,6 +79,7 @@ private void installActions(List actions) { final Object interceptor = action.getActionInterceptor(traceAgentArgs); if (interceptor != null) { new AgentBuilder.Default() + .with(new AgentBuilder.InitializationStrategy.SelfInjection.Eager()) .type(action.getClassMatcher()) .transform( (builder, type, classLoader, module) -> @@ -117,4 +118,8 @@ public static void premain(String arguments, Instrumentation instrumentation) { TraceAgent traceAgent = new TraceAgent(traceAgentArgs, instrumentation); traceAgent.install(); } + + public static void agentmain(String arguments, Instrumentation instrumentation) { + premain(arguments, instrumentation); + } }