92
バババババババババ ババババババババ バババババ ババババババババ / バ西 Java バババババババ ババ バ(@jyukutyo) #ccc_i61

JJUG CCC 2016 fall バイトコードが君のトモダチになりたがっている

Embed Size (px)

Citation preview

Seasar2

/ Java (@jyukutyo)

#ccc_i61

#ccc_i31

( )@jyukutyo Java 2009 / 500SI 9 / 5blog : Fight the Future http://jyukutyo.hatenablog.comJJUG CCC2016 Spring2015 Spring

!!

#ccc_i612

#ccc_j33

#ccc_j34

JavaJava

Java#ccc_j35

(bytecode) https://ja.wikipedia.org/wiki/#ccc_j36

#ccc_j37

JavaScalaJRubyGroovy

Compiler

Classfile

cafe babe0000 00320017 0100JVMClassfileClassfileClassfileClassfileClassfile

(JIT)

Java#ccc_j38

#ccc_j39

#ccc_j310cafe babe 0000 0032 0017 0100 0a48 656c6c6f 576f 726c 6407 0001 0100 106a 6176612f 6c61 6e67 2f4f 626a 6563 7407 00030100 1048 656c 6c6f 576f 726c 642e 7363616c 6101 001e 4c73 6361 6c61 2f72 65666c65 6374 2f53 6361 6c61 5369 676e 61747572 653b 0100 0562 7974 6573 0100 ef060115 3a51 2101 0209 0215 0921 0253 336d593e 3c76 4e1d 3765 1505 1911 6102 1f665b42 2418 5050 0201 2109 3171 2144 01030d15 4121 0123 010a 0529 4155 0d1c 3770...(Emacshexl-find-file)

HelloWorld#ccc_j311

#ccc_j312

#ccc_j313

#ccc_j314

#ccc_j315cafe babe 0000 0032 0017 0100 0a48 656c6c6f 576f 726c 6407 0001 0100 106a 6176612f 6c61 6e67 2f4f 626a 6563 7407 00030100 1048 656c 6c6f 576f 726c 642e 7363616c 6101 001e 4c73 6361 6c61 2f72 65666c65 6374 2f53 6361 6c61 5369 676e 61747572 653b 0100 0562 7974 6573 0100 ef060115 3a51 2101 0209 0215 0921 0253 336d593e 3c76 4e1d 3765 1505 1911 6102 1f665b42 2418 5050 0201 2109 3171 2144 01030d15 4121 0123 010a 0529 4155 0d1c 3770...

1!#ccc_j316

#ccc_j317

Javassist Seasar2HibernateByteman JBossHibernatecglib SpringMockitoByte Buddy MockitoSpockObjectWeb ASM GuiceSpockBCEL #ccc_j318

#ccc_j319

javapjavapJavaJDK`javap -v []`#ccc_j320

javap -v HelloWorld#ccc_j321

#ccc_j322public class HelloWorld minor version: 0 major version: 52Constant pool: #1 = Methodref #6.#15 // java/lang/Object."":()V #2 = Fieldref #16.#17 // java/lang/System.out:Ljava/io/PrintStream; #3 = String #18 // Hello, world! #4 = Methodref #19.#20 // java/io/PrintStream.println:(Ljava/lang/String;)V...

#ccc_j323...public static voidmain(java.lang.String[]); Code: 0: getstatic #2 3: ldc #3 5: invokevirtual #4 8: return-- #0 = index of Constant pool...

#ccc_j324

#ccc_j325

Java AgentMavenGradleAnt#ccc_j326

Java Agent#ccc_j327

Java#ccc_j328

http://itpro.nikkeibp.co.jp/article/COLUMN/20061208/256374/

Java Agent#ccc_j329

#ccc_j330

#ccc_j331import java.lang.instrument.ClassFileTransformer;import java.lang.instrument.Instrumentation;

public class Agent { public static void premain(String agentArgs, Instrumentation inst) { inst.addTransformer(new ClassFileTransformer() { @Override public byte[] transform(ClassLoader loader,String className, Class classBeingRedefined, ProtectionDomain protectionDomain,byte[] classfileBuffer) throws IllegalClassFormatException { // } }); }}

premain()main()#ccc_j332

ClassFileTransformer#ccc_j333

Instrument API#ccc_j334

https://docs.oracle.com/javase/jp/7/api/java/lang/instrument/package-summary.html

Java Agent#ccc_j335

MANIFEST.MF#ccc_j336

MANIFEST.MFPremain-Classpremain()

#ccc_j337

MANIFEST.MFBoot-Class-Path JARJAR

#ccc_j338

#ccc_j339META-INF/MANIFEST.MF

Manifest-Version: 1.0Premain-Class: com.jyukutyo.AgentBoot-Class-Path: javassist-3.21.0-GA.jarCreated-By: Apache Maven 3.2.2Build-Jdk: 1.8.0_102

#ccc_j340

#ccc_j341public class Agent { public static void premain(String agentArgs, Instrumentation inst) { inst.addTransformer(new ClassFileTransformer() { @Override public byte[] transform(.., String className,..) { System.out.println(className); ... } }); }}

MANIFEST.MFJAR#ccc_j342

HelloWorld

java -javaagent:agent.jarexample.HelloWorld#ccc_j343

#ccc_j344java/lang/invoke/MethodHandleImpl...java/lang/invoke/MemberName$Factoryjava/lang/invoke/MethodHandleStaticsjava/lang/invoke/MethodHandleStatics$1sun/misc/PostVMInitHooksun/usagetracker/UsageTrackerClientjava/util/concurrent/atomic/AtomicBoolean...sun/launcher/LauncherHelperexample/HelloWorldsun/launcher/LauncherHelper$FXHelperjava/lang/Class$MethodArrayjava/lang/VoidHello World!...

(ClassFileTransformer)#ccc_j345

Javassist#ccc_j346

#ccc_j347

#ccc_j348public class Agent { public static void premain(...) { inst.addTransformer(new ClassFileTransformer() { public byte[] transform(..., byte[] classfile) { ... ClassPool cp = ClassPool.getDefault(); try { CtClass ct = cp.makeClass(new ByteArrayInputStream(classfile)); for (CtMethod cm: ct.getDeclaredMethods()) { cm.insertBefore("System.out.println($args); System.out.println($type);"); } return ct.toBytecode();

} catch (IOException | CannotCompileException e) { ...

HelloWorld

java -javaagent:agent.jarexample.HelloWorld#ccc_j349

#ccc_j350[Ljava.lang.Object;@754ba872voidHello World!

Javassist#ccc_j351

Javassit#ccc_j352

#ccc_j353 ClassPool cp = ClassPool.getDefault(); try { CtClass ct = cp.makeClass(new ByteArrayInputStream(classfile));CtClass

#ccc_j354 for (CtMethod cm: ct.getDeclaredMethods()) { cm.insertBefore("System.out.println($args); System.out.println($type);"); }CtClassCtMethodprintln()2

$#ccc_j355

$argsObject$typejava.lang.Class $classClass$_

https://jboss-javassist.github.io/javassist/tutorial/tutorial2.html

JavassitOSS#ccc_j356

Hibernate

#ccc_j357public synchronized byte[] enhance(String className, byte[] originalBytes) throws EnhancementException { try { final CtClass managedCtClass = classPool.makeClassIfNew( new ByteArrayInputStream(originalBytes)); if (enhance(managedCtClass)) { return getByteCode(managedCtClass); } else { return null; } } catch (IOException e) { log.unableToBuildEnhancementMetamodel(className); return null; }}org.hibernate.bytecode.enhance.internal.javassist.EnhancerImpl

#ccc_j358

JavaOSS#ccc_j359

JMockit

#ccc_j360public static void premain(String agentArgs, @Nonnull Instrumentation inst) throws IOException{ initialize(true, inst);}mockit.internal.startup.Startup

#ccc_j361

BytemancglibByte BuddyObjectWeb ASMBCEL#ccc_j362

(Javassit)#ccc_j363

BytemanRuleRule#ccc_j364

BytemanRule

#ccc_j365RULE hello worldCLASS com.jyukutyo.MainMETHOD mainAT ENTRYIF TRUE DO traceStack()ENDRULERule

#ccc_j366$ java -javaagent:byteman-3.0.6.jar=script:rule.btmcom.jyukutyo.Main(1)

Stack trace for thread maincom.jyukutyo.Main.main(Main.java:-1)Hello World!

Rule

Byte Buddy2015 Dukes Choice Award #ccc_j367

#ccc_j368public class Agent { public static void premain(String agentArgs, Instrumentation inst) { new AgentBuilder.Default() .type(ElementMatchers.any()) .transform(new AgentBuilder.Transformer() { @Override public DynamicType.Builder transform(DynamicType.Builder builder, TypeDescription typeDescription, ClassLoader classloader) { return builder.method( ElementMatchers.named("toString")) .intercept(FixedValue.value("transformed")); } }).installOn(inst); }}

toString()transform#ccc_j369

#ccc_j370$ java com.jyukutyo.Main

toString() is called.

$ java -javaagent:agent.jar com.jyukutyo.Main

transformed

()

#ccc_j371public class Agent { public static void premain(String agentArgs, Instrumentation inst) { new AgentBuilder.Default() .type(ElementMatchers.any()) .transform(new AgentBuilder.Transformer() { @Override public DynamicType.Builder transform(DynamicType.Builder builder, TypeDescription typeDescription, ClassLoader classloader) { return builder.method( ElementMatchers.named("toString")) .intercept(FixedValue.value("transformed")); } }).installOn(inst); }}

Web#ccc_j372

Attach API#ccc_j373

Attach APIJVMAPIcom.sun.tools.attachcom.sun.tools.attach.spiHotSpot VM#ccc_j374

Byte BuddyJavaAttach API#ccc_j375

Byte BuddyByteBuddyAgent#ccc_j376

#ccc_j377

Attach API#ccc_j378

#ccc_j379VirtualMachine vm = VirtualMachine.attach(9999");

vm.loadAgent(agent.jar");vm.detach();

pid

#ccc_j380

Attach API/tools.jar#ccc_j381

Spring Boot Web/testhello transformed #ccc_j382

SpringController

#ccc_j383@Controllerpublic class TestController {

@ResponseBody @RequestMapping(value = "test", method = RequestMethod.GET) public String index() { return "hello"; }}

#ccc_j384public static void agentmain(... inst) { ... String target = "com.jyukutyo.TestController; ByteBuddy byteBuddy = new ByteBuddy(); byteBuddy.redefine(TypePool.Default.of(classLoader) .describe(target).resolve(), ClassFileLocator.ForClassLoader.of(classLoader)) .method(ElementMatchers.named("index")) .intercept(FixedValue.value("transformed")) .make() .load(classLoader, ClassReloadingStrategy.of(inst));

new AgentBuilder.Default().with(byteBuddy) .installOn(inst);}

#ccc_j385public static void agentmain( String agentArgs, Instrumentation inst) throws Exception {VMpremain()agentmain()

#ccc_j386.method(ElementMatchers.named("index")).intercept(FixedValue.value("transformed"))

index()transformed

#ccc_j387MANIFEST.MF...Agent-Class: com.jyukutyo.AgentCan-Retransform-Classes: true

#ccc_j388mvn spring-boot:runhttp://localhost:8080/testjava -cp /Library/Java/JavaVirtualMachines/jdk1.8.0_102.jdk/Contents/Home/lib/tools.jar:. com.jyukutyo.Main [pid]http://localhost:8080/test

- Byte BuddyJava Attach API #ccc_j389

#ccc_j390

Q&A#ccc_j391