More Related Content
Similar to JJUG CCC 2016 fall バイトコードが君のトモダチになりたがっている (20)
More from Koichi Sakata (20)
JJUG CCC 2016 fall バイトコードが君のトモダチになりたがっている
- 2. #ccc_i3 1
阪田 浩一 (さかた こういち)
@jyukutyo じゅくちょー
フリュー株式会社
元塾講師アルバイト
関西Javaエンジニアの会(関ジャバ) 会長
2009年 発足 / メンバー数 500人以上
SIでの客先常駐 9年 / 自社サービス 5年目
blog : Fight the Future http://jyukutyo.hatenablog.com
JJUG CCCでは2016 Spring、2015 Springで登壇
- 11. #ccc_j3 10
cafe babe 0000 0032 0017 0100 0a48 656c
6c6f 576f 726c 6407 0001 0100 106a 6176
612f 6c61 6e67 2f4f 626a 6563 7407 0003
0100 1048 656c 6c6f 576f 726c 642e 7363
616c 6101 001e 4c73 6361 6c61 2f72 6566
6c65 6374 2f53 6361 6c61 5369 676e 6174
7572 653b 0100 0562 7974 6573 0100 ef06
0115 3a51 2101 0209 0215 0921 0253 336d
593e 3c76 4e1d 3765 1505 1911 6102 1f66
5b42 2418 5050 0201 2109 3171 2144 0103
0d15 4121 0123 010a 0529 4155 0d1c 3770
...(Emacsのhexl-find-fileなどで開く)
- 16. #ccc_j3 15
cafe babe 0000 0032 0017 0100 0a48 656c
6c6f 576f 726c 6407 0001 0100 106a 6176
612f 6c61 6e67 2f4f 626a 6563 7407 0003
0100 1048 656c 6c6f 576f 726c 642e 7363
616c 6101 001e 4c73 6361 6c61 2f72 6566
6c65 6374 2f53 6361 6c61 5369 676e 6174
7572 653b 0100 0562 7974 6573 0100 ef06
0115 3a51 2101 0209 0215 0921 0253 336d
593e 3c76 4e1d 3765 1505 1911 6102 1f66
5b42 2418 5050 0201 2109 3171 2144 0103
0d15 4121 0123 010a 0529 4155 0d1c 3770
...
- 23. #ccc_j3 22
public class HelloWorld
minor version: 0
major version: 52
Constant pool:
#1 = Methodref #6.#15 //
java/lang/Object."<init>":()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/Strin
g;)V
...
- 24. #ccc_j3 23
...
public static void
main(java.lang.String[]);
Code:
0: getstatic #2
3: ldc #3
5: invokevirtual #4
8: return
-- #0 = index of Constant pool
...
- 32. #ccc_j3 31
import 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 {
// ライブラリを使ってクラスの処理を変更する!
}
});
}
}
- 42. #ccc_j3 41
public class Agent {
public static void premain(String agentArgs,
Instrumentation inst) {
inst.addTransformer(new ClassFileTransformer() {
@Override
public byte[] transform(..,
String className,..)
{
System.out.println(className);
...
}
});
}
}
- 49. #ccc_j3 48
public 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) {
...
- 54. #ccc_j3 53
ClassPool cp = ClassPool.getDefault();
try {
CtClass ct = cp.makeClass(
new ByteArrayInputStream(classfile));
クラスファイルの
バイトコードを表す
バイト配列から
CtClassを生成
- 55. #ccc_j3 54
for (CtMethod cm: ct.getDeclaredMethods()) {
cm.insertBefore("System.out.println($args);
System.out.println($type);");
}
CtClassからCtMethodを
取得して、
処理の前にprintln()を
2行挿入
- 58. Hibernate
#ccc_j3 57
public 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
- 61. JMockit
#ccc_j3 60
public static void premain(String agentArgs,
@Nonnull Instrumentation inst) throws IOException
{
initialize(true, inst);
}
mockit.internal.startup.Startup
- 69. エージェントの実装
#ccc_j3 68
public 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);
}
}
- 71. #ccc_j3 70
$ java com.jyukutyo.Main
toString() is called.
$ java -javaagent:agent.jar com.jyukutyo.Main
transformed
- 72. エージェントの実装(再掲)
#ccc_j3 71
public 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);
}
}
- 85. エージェントの実装
#ccc_j3 84
public 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);
}
- 86. #ccc_j3 85
public static void agentmain(
String agentArgs, Instrumentation inst) throws Exception {
VM起動中にエージェントを
ロードさせたい場合は
premain()ではなく
agentmain()を定義する
- 89. #ccc_j3 88
1. mvn spring-boot:run
2. http://localhost:8080/test
3. java -cp
/Library/Java/JavaVirtualMachines/jdk1.8.0_102.jdk/Conte
nts/Home/lib/tools.jar:. com.jyukutyo.Main [pid]
4. http://localhost:8080/test
デモ