Oredev 2015 - Taming Java Agents
-
Upload
anton-arhipov -
Category
Technology
-
view
1.220 -
download
2
Transcript of Oredev 2015 - Taming Java Agents
Taming Java Agents@antonarhipov
Agenda
• Overview of Java agent technology
• Instrumentation API
• Attach API
• HacksApplicationshttp://xkcd.com/138/
BTrace
Pretty much every APM tool today uses Java Agents to instrument the application
A lightweight profiler for Java web apps
A lightweight profiler for Java web apps
A lightweight profiler for Java web apps
A lightweight profiler for Java web apps
A lightweight profiler for Java web apps
A lightweight profiler for Java web apps
my.war
ClassLoader
getResource("hello.html"); read("src/main/.../hello.html");
rebel.xml
• Maps the running application to IDE workspace• Reloads Java classes and framework configurations in
a running JVM process
This slide is intentionally left blank
public static void main(String[] args) { for (String arg : args) { new Thread(new Runnable() { public void run() { //.... } }).start();
Java app
public static void main(String[] args) { for (String arg : args) { new Thread(new Runnable() { public void run() { //..... } }).start();
RULE trace thread start CLASS java.lang.Thread METHOD start() IF true DO traceln("*** start for thread: "+ $0.getName()) ENDRULE
Java app
Bytemanrule
public static void main(String[] args) { for (String arg : args) { new Thread(new Runnable() { public void run() { //..... } }).start();
RULE trace thread start CLASS java.lang.Thread METHOD start() IF true DO traceln("*** start for thread: "+ $0.getName()) ENDRULE
> java -javaagent:byteman.jar=script:thread.btm,boot:byteman.jar \ -Dorg.jboss.byteman.transform.all org.my.AppMain2 foo bar baz *** start for thread: foo foo *** start for thread: bar bar *** start for thread: baz baz
Java app
Bytemanrule
public static void main(String[] args) { for (String arg : args) { new Thread(new Runnable() { public void run() { //..... } }).start();
RULE trace thread start CLASS java.lang.Thread METHOD start() IF true DO traceln("*** start for thread: "+ $0.getName()) ENDRULE
Java app
Bytemanrule
public static void main(String[] args) { for (String arg : args) { new Thread(new Runnable() { public void run() { //..... } }).start();
RULE trace thread start CLASS java.lang.Thread METHOD start() IF true DO traceln("*** start for thread: "+ $0.getName()) ENDRULE
> java -classpath byteman-install.jar \ org.jboss.byteman.agent.install.Install 13101
Java app
Bytemanrule
Install agent:
public static void main(String[] args) { for (String arg : args) { new Thread(new Runnable() { public void run() { //..... } }).start();
RULE trace thread start CLASS java.lang.Thread METHOD start() IF true DO traceln("*** start for thread: "+ $0.getName()) ENDRULE
> java -classpath byteman-install.jar \ org.jboss.byteman.agent.install.Install 13101
Java app
Bytemanrule
> java -classpath byteman-submit.jar \ org.jboss.byteman.agent.submit.Submit -l thread.btm
Install agent:
Submit rules:
http://byteman.jboss.org
Java Agent Overview
import java.lang.instrument.ClassFileTransformer;import java.lang.instrument.Instrumentation;
public class Agent {
public static void premain(String args, Instrumentation inst) { inst.addTransformer(new ClassFileTransformer { … }); }
public static void agentmain(String args, Instrumentation inst) { premain(args, inst); }
}
META-‐INF/MANIFEST.MF Premain-‐Class: Agent
$> java –javaagent:agent.jar application.Main
java.lang.instrument.ClassFileTransformer
public class MyTransformer implements ClassFileTransformer { public void byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain pd, byte[] classfileBuffer){
ClassPool cp = ClassPool.getDefault(); CtClass ct = cp.makeClass(new ByteArrayInputStream(classfileBuffer));
// transform the bytes as required, // for instance - with Javassist return ct.toBytecode(); }}
Class loading
Instrumentation
Class loading
ClassFileTransformer
ClassFileTransformer
ClassFileTransformer
Instrumentation
Class loading
ClassFileTransformer
ClassFileTransformer
ClassFileTransformer
Javassist
ASM
Instrumentation
Bytebuddy
https://github.com/zeroturnaround/callspy
Instrumentation API
java.lang.instrument.Instrumentation
void addTransformer(ClassFileTransformer transformer, boolean canRetransform);
void appendToBootstrapClassLoaderSearch(JarFile jarfile);void appendToSystemClassLoaderSearch(JarFile jarfile);
Class[] getAllLoadedClasses();Class[] getInitiatedClasses(ClassLoader loader); void redefineClasses(ClassDefinition... classes);void retransformClasses(Class<?>... classes);
JVM JVM
Process 1 Process 2
Agent
-cp tools.jar
Attach API
• Executed when the agent attaches to the running JVM
• Instrumentation parameter is optional
• META-INF/MANIFEST.MF is required
• Requires support for loading agents in JVM
• Allows adding the code to JVM post-factum
public static void agentmain(String args, Instrumentation inst)
import com.sun.tools.attach.VirtualMachine;
//attach to target VMVirtualMachine vm = VirtualMachine.attach("2177");
//get system properties in the target VMProperties props = vm.getSystemProperties();
//load agent into the VMvm.loadAgent("agent.jar", "arg1=x,arg2=y");
//detach from VMvm.detach();
http://docs.oracle.com/javase/7/docs/jdk/api/attach/spec/com/sun/tools/attach/VirtualMachine.html
https://gist.github.com/nickman/6494990
https://github.com/antonarhipov/attach-and-transform-with-mbeans
https://speakerdeck.com/antonarhipov
http://www.slideshare.net/arhan
Resourceshttp://byteman.jboss.org
http://www.javassist.org
https://github.com/zeroturnaround/callspy
https://github.com/antonarhipov/attach-and-transform-with-mbeans
https://docs.oracle.com/javase/8/docs/api/java/lang/instrument/package-summary.html
http://docs.oracle.com/javase/8/docs/jdk/api/attach/spec/com/sun/tools/attach/VirtualMachine.html
http://asm.ow2.org/ http://bytebuddy.net/