SlideShare une entreprise Scribd logo
1  sur  58
Koichi Sakata
PONOS Corporation
Bytecode Manipulation
with a Java Agent
and Byte Buddy
About Me
• Koichi Sakata (阪田 浩一)
• KanJava JUG Leader
• Java Champion
• PONOS Corporation
#oc1bcm2
Intended Audience
• Those who want to start manipulating
bytecode
• Not for experts
#oc1bcm3
javac
Java Bytecode
#oc1bcm
.java • Java Code
.class • Bytecode
Gets loaded by JVM
4
What is bytecode manipulation?
• Editing bytecode in the class files
–Add
–Delete
–Replace
#oc1bcm5
Why do we manipulate?
It's fun!
#oc1bcm6
Not Only Fun
• To change code at runtime
–Generate Entity objects in Hibernate
–Create mock objects in Mockito
#oc1bcm7
Bytecode Manipulation
• Hard to manipulate by hand...
– A class file is a binary file
– JVM has a verification process
#oc1bcm8
Bytecode Manipulation Libraries
• Byte Buddy
• Byteman
• Javassist
• cglib
• ASM
• Apache Commons BCEL
#oc1bcm9
Byte Buddy
• http://bytebuddy.net
• Easy-to-use API
• Java 11 Support
• Duke's Choice Award 2015 Winner
#oc1bcm10
Byte Buddy
• Usage in major libraries
–Hibernate
–Mockito
–Jackson
–etc.
#oc1bcm11
Class<?> subClass = new ByteBuddy()
.subclass(Object.class)
.method(ElementMatchers.named("toString"))
.intercept(FixedValue.value("Hello World!"))
.make()
.load(getClass().getClassLoader())
.getLoaded();
Hello World in Byte Buddy
#oc1bcm12
Class<?> subClass = new ByteBuddy()
.subclass(Object.class)
.method(ElementMatchers.named("toString"))
1. Create a subclass of Object
2. Choose the toString()
Hello World in Byte Buddy
#oc1bcm13
.method(ElementMatchers.named("toString"))
.intercept(FixedValue.value("Hello World!"))
1. Intercept toString() to return a fixed
string value "Hello World"
Hello World in Byte Buddy
#oc1bcm14
.make()
.load(getClass().getClassLoader())
.getLoaded();
1. Make a new type (unloaded class)
2. Load the type
3. Get the new loaded class
Hello World in Byte Buddy
#oc1bcm15
Class<?> subClass = new ByteBuddy()
.subclass(Object.class)
.method(ElementMatchers.named("toString"))
.intercept(FixedValue.value("Hello World!"))
.make()
.load(getClass().getClassLoader())
.getLoaded();
Hello World in Byte Buddy
#oc1bcm16
Demo 1
• Run Hello World
–See a generated class
#oc1bcm17
Demo code is available
• http://bit.ly/oc1bcm
–github.com/jyukutyo/SampleCodeForByt
eBuddySeeesion
#oc1bcm18
Usage in Mockito
• SubclassBytecodeGenerator
–mockClass()
#oc1bcm19
How to use BM?
1. Directly in your application
2. At build time via Maven/Gradle
3. With Java Agent
– No need for changing code
– Detachable
#oc1bcm20
Java Agent?
• Do espionage activities in
your application
– Profiling
– Logging
– Changing the target
application itself
#oc1bcm21
Java Agent
• Instrument programs running on the
JVM
–JSR 163: JavaTM Platform Profiling
Architecture
–JVM calls Java Agent method with
proper timing
#oc1bcm22
Create a Java Agent
• Just define methods
–premain() Method
–agentmain() Method
#oc1bcm23
Create a Java Agent
• premain() Method
–Gets called before main() method
• agentmain() Method
–Gets called when the agent is attached
after JVM startup
#oc1bcm24
With Java Agent
We can run bytecode
manipulation code
at runtime
#oc1bcm25
#oc1bcm26
premain()
public static void premain(String agentArgs,
Instrumentation inst)
• Provides opportunity to modify
classes before loading
–Instrumentation class has useful
methods
#oc1bcm27
Premain-Class: com.s.logging.LoggingAgent
Boot-Class-Path: byte-buddy-1.8.22.jar
MANIFEST.MF
#oc1bcm28
Demo 2
• Create a simple Java Agent
#oc1bcm29
Another Example
• Add outputting logs before executing
a particular method on a particular
class
#oc1bcm30
Example
1. Manipulate bytecode before loading
–Use premain()
2. Replace the class file
–Use ByteBuddy
–Not create a subclass
#oc1bcm31
public class Target {
public void foo() {
System.out.println("foo!");
}
public static void main(String[] args) {
new Target().foo();
}
}
Target Class
#oc1bcm32
TypePool pool = TypePool.Default.ofClassPath();
return new ByteBuddy()
.rebase(pool.describe("c.Target").resolve(),
ClassFileLocator.ForClassLoader
.ofClassPath()
)
Replace the class
#oc1bcm33
return new ByteBuddy()
.rebase(...)
• Replace the original implementation with
new one
• Save the original implementation under a
different method name
Replace the class
#oc1bcm34
Enhance Existing Method
• ByteBuddy#subclass()
–Override the method
• ByteBuddy#redefine()
–Replace the implementation
• ByteBuddy#rebase()
–Copy&Rename the method
–Replace the implementation
#oc1bcm35
TypePool pool = TypePool.Default.ofClassPath();
return new ByteBuddy()
.rebase(pool.describe("c.Target")
.resolve(),
• Can't use a class literal
– JVM loads class before changing the class
• Use the TypePool class and describe()
Replace the class
#oc1bcm36
.rebase(pool.describe(...).resolve(),
ClassFileLocator.ForClassLoader
.ofClassPath()
)
• Allow to locate a class file
• ofClassPath() - Scan the running
application's class path
Replace the class
#oc1bcm37
return new ByteBuddy()
...
.method(ElementMatchers.named("foo"))
.intercept(
MethodDelegation
.to(LoggingInterceptor.class)
.andThen(SuperMethodCall.INSTANCE)
)
Intercept the method
#oc1bcm38
Delegation
• MethodDelegation.to()
–Specify a Class to delegate
• A best match method is used
#oc1bcm39
return new ByteBuddy()
...
.method(ElementMatchers.named("foo"))
.intercept(
MethodDelegation
.to(LoggingInterceptor.class)
.andThen(SuperMethodCall.INSTANCE)
)
Intercept the method
#oc1bcm40
public static class LoggingInterceptor {
public static void intercept(
@Origin Method m) {
...println("Call " + m.getName()...);
}
}
Interceptor Class
#oc1bcm41
Delegated Method
• Annotations for Parameter
–@Origin
• Reference to the method/constructor
#oc1bcm42
Delegated Method
• Annotations for Parameter
–@This/@Super
• Dynamic/Super type's instance
–@Argument, @AllArguments
–@SuperCall
• Callable/Runnable instance of the super's
implementation of the method
#oc1bcm43
public static void premain(String args,
Instrumentation inst) {
inst.addTransformer(
new ClassFileTransformer() {
@Override
public byte[] transform(...) {
premain()
#oc1bcm44
public byte[] transform(ClassLoader loader,
String className,
Class<?> classBeingRedefined,
ProtectionDomain protectionDomain,
byte[] classfileBuffer) {
// Call ByteBuddy
}
transform()
#oc1bcm45
public byte[] transform(ClassLoader loader,
String className,
Class<?> classBeingRedefined,
ProtectionDomain protectionDomain,
byte[] classfileBuffer)
• className – Class name to be loaded
• classfileBuffer – Class file content
transform()
#oc1bcm46
public byte[] transform(ClassLoader loader,
String className,
Class<?> classBeingRedefined,
ProtectionDomain protectionDomain,
byte[] classfileBuffer)
• Return the class file content
transform()
#oc1bcm47
Demo 3
• Add outputting logs before executing
a method
#oc1bcm48
#oc1bcm49
Features in ByteBuddy
• Add fields/methods
• Manipulate stack
• Generate CONDY bytecode
– Constant Dynamic – JEP 309
• Simplify Java Agent with AgentBuilder
• lots of other features
#oc1bcm50
Byte Buddy's AgentBuilder
• Simplify the Java Agent
implementation
#oc1bcm51
new AgentBuilder.Default()
.type(ElementMatchers.named("com.sakatakoic
hi.logging.Target"))
.transform(new AgentBuilder.Transformer() {
...
})
.installOn(inst);
AgentBuilder
#oc1bcm52
AgentBuilder
1. Use AgentBuilder
–instead of ByteBuddy class
2. Use AgentBuilder.Transformer
–instead of ClassFileTransformer
3. Call installOn()
#oc1bcm53
.transform(new AgentBuilder.Transformer() {
public DynamicType.Builder<?> transform(
DynamicType.Builder<?> builder,
TypeDescription typeDescription,
ClassLoader classLoader,
JavaModule javaModule) {
return builder
.method(ElementMatch...named("foo"))
.intercept(...);
}
})
Transformer
#oc1bcm54
Without -javaagent
• -javaagent option can be removed
–Call ByteBuddyAgent.install()
–Call AgentBuilder#installOnByteBuddyAgent()
• instead of installOn()
–Need to add byte-buddy-agent.jar
#oc1bcm55
ByteBuddyAgent.install();
new AgentBuilder.Default()
.type(ElementMatchers.named("com.sakatakoic
hi.logging.Target"))
.transform(new AgentBuilder.Transformer() {
...
})
.installOnByteBuddyAgent();
Without -javaagent
#oc1bcm56
Demo 4
• Add outputting logs without
-javaagent option
#oc1bcm57
Wrap Up
• BM is fun and close to us!
–Many libraries are using
• Application Examples
–Hot Swap
–Advanced Dynamic Proxy
#oc1bcm58

Contenu connexe

Tendances

Serial Killer - Silently Pwning your Java Endpoints // OWASP BeNeLux Day 2016
Serial Killer - Silently Pwning your Java Endpoints // OWASP BeNeLux Day 2016Serial Killer - Silently Pwning your Java Endpoints // OWASP BeNeLux Day 2016
Serial Killer - Silently Pwning your Java Endpoints // OWASP BeNeLux Day 2016
Christian Schneider
 
試験にでるSpring
試験にでるSpring試験にでるSpring
試験にでるSpring
土岐 孝平
 

Tendances (20)

JavaでWebサービスを作り続けるための戦略と戦術 JJUG-CCC-2018-Spring-g1
JavaでWebサービスを作り続けるための戦略と戦術 JJUG-CCC-2018-Spring-g1JavaでWebサービスを作り続けるための戦略と戦術 JJUG-CCC-2018-Spring-g1
JavaでWebサービスを作り続けるための戦略と戦術 JJUG-CCC-2018-Spring-g1
 
Spring Framework - AOP
Spring Framework - AOPSpring Framework - AOP
Spring Framework - AOP
 
使ってみよう!JDK Flight Recorder
使ってみよう!JDK Flight Recorder使ってみよう!JDK Flight Recorder
使ってみよう!JDK Flight Recorder
 
Serial Killer - Silently Pwning your Java Endpoints // OWASP BeNeLux Day 2016
Serial Killer - Silently Pwning your Java Endpoints // OWASP BeNeLux Day 2016Serial Killer - Silently Pwning your Java Endpoints // OWASP BeNeLux Day 2016
Serial Killer - Silently Pwning your Java Endpoints // OWASP BeNeLux Day 2016
 
Micrometerでメトリクスを収集してAmazon CloudWatchで可視化
Micrometerでメトリクスを収集してAmazon CloudWatchで可視化Micrometerでメトリクスを収集してAmazon CloudWatchで可視化
Micrometerでメトリクスを収集してAmazon CloudWatchで可視化
 
Javaバイトコード入門
Javaバイトコード入門Javaバイトコード入門
Javaバイトコード入門
 
スレッドダンプの読み方
スレッドダンプの読み方スレッドダンプの読み方
スレッドダンプの読み方
 
Non blocking io with netty
Non blocking io with nettyNon blocking io with netty
Non blocking io with netty
 
Part II: LLVM Intermediate Representation
Part II: LLVM Intermediate RepresentationPart II: LLVM Intermediate Representation
Part II: LLVM Intermediate Representation
 
外部キー制約に伴うロックの小話
外部キー制約に伴うロックの小話外部キー制約に伴うロックの小話
外部キー制約に伴うロックの小話
 
Devoxx France 2023 - Les nouveautés de Java 19 et 20
Devoxx France 2023 - Les nouveautés de Java 19 et 20Devoxx France 2023 - Les nouveautés de Java 19 et 20
Devoxx France 2023 - Les nouveautés de Java 19 et 20
 
Spring boot - an introduction
Spring boot - an introductionSpring boot - an introduction
Spring boot - an introduction
 
Formation Spring Avancé gratuite par Ippon 2014
Formation Spring Avancé gratuite par Ippon 2014Formation Spring Avancé gratuite par Ippon 2014
Formation Spring Avancé gratuite par Ippon 2014
 
KSUG 스프링캠프 2019 발표자료 - "무엇을 테스트할 것인가, 어떻게 테스트할 것인가"
KSUG 스프링캠프 2019 발표자료 - "무엇을 테스트할 것인가, 어떻게 테스트할 것인가"KSUG 스프링캠프 2019 발표자료 - "무엇을 테스트할 것인가, 어떻게 테스트할 것인가"
KSUG 스프링캠프 2019 발표자료 - "무엇을 테스트할 것인가, 어떻게 테스트할 것인가"
 
C#の強み、或いは何故PHPから乗り換えるのか
C#の強み、或いは何故PHPから乗り換えるのかC#の強み、或いは何故PHPから乗り換えるのか
C#の強み、或いは何故PHPから乗り換えるのか
 
Java 11 to 17 : What's new !?
Java 11 to 17 : What's new !?Java 11 to 17 : What's new !?
Java 11 to 17 : What's new !?
 
jcmd をさわってみよう
jcmd をさわってみようjcmd をさわってみよう
jcmd をさわってみよう
 
試験にでるSpring
試験にでるSpring試験にでるSpring
試験にでるSpring
 
バイナリアンを目指して For a binaryen
バイナリアンを目指して For a binaryenバイナリアンを目指して For a binaryen
バイナリアンを目指して For a binaryen
 
Fast as C: How to Write Really Terrible Java
Fast as C: How to Write Really Terrible JavaFast as C: How to Write Really Terrible Java
Fast as C: How to Write Really Terrible Java
 

Similaire à Bytecode Manipulation with a Java Agent and Byte Buddy

Baab (Bug as a Backdoor) through automatic exploit generation (CRAX)
Baab (Bug as a Backdoor) through automatic exploit generation (CRAX)Baab (Bug as a Backdoor) through automatic exploit generation (CRAX)
Baab (Bug as a Backdoor) through automatic exploit generation (CRAX)
Shih-Kun Huang
 
Invoke dynamic your api to hotspot
Invoke dynamic your api to hotspotInvoke dynamic your api to hotspot
Invoke dynamic your api to hotspot
Boundary
 
Lecture from javaday.bg by Nayden Gochev/ Ivan Ivanov and Mitia Alexandrov
Lecture from javaday.bg by Nayden Gochev/ Ivan Ivanov and Mitia Alexandrov Lecture from javaday.bg by Nayden Gochev/ Ivan Ivanov and Mitia Alexandrov
Lecture from javaday.bg by Nayden Gochev/ Ivan Ivanov and Mitia Alexandrov
Nayden Gochev
 

Similaire à Bytecode Manipulation with a Java Agent and Byte Buddy (20)

Byte code manipulation and instrumentalization in Java
Byte code manipulation and instrumentalization in JavaByte code manipulation and instrumentalization in Java
Byte code manipulation and instrumentalization in Java
 
Easymock
EasymockEasymock
Easymock
 
Baab (Bug as a Backdoor) through automatic exploit generation (CRAX)
Baab (Bug as a Backdoor) through automatic exploit generation (CRAX)Baab (Bug as a Backdoor) through automatic exploit generation (CRAX)
Baab (Bug as a Backdoor) through automatic exploit generation (CRAX)
 
VMs, Interpreters, JIT
VMs, Interpreters, JITVMs, Interpreters, JIT
VMs, Interpreters, JIT
 
Sista: Improving Cog’s JIT performance
Sista: Improving Cog’s JIT performanceSista: Improving Cog’s JIT performance
Sista: Improving Cog’s JIT performance
 
Game of Performance: A Song of JIT and GC
Game of Performance: A Song of JIT and GCGame of Performance: A Song of JIT and GC
Game of Performance: A Song of JIT and GC
 
AOP on Android
AOP on AndroidAOP on Android
AOP on Android
 
Why GC is eating all my CPU?
Why GC is eating all my CPU?Why GC is eating all my CPU?
Why GC is eating all my CPU?
 
mjprof: Monadic approach for JVM profiling
mjprof: Monadic approach for JVM profilingmjprof: Monadic approach for JVM profiling
mjprof: Monadic approach for JVM profiling
 
5장. Execution Engine
5장. Execution Engine5장. Execution Engine
5장. Execution Engine
 
Triton and Symbolic execution on GDB@DEF CON China
Triton and Symbolic execution on GDB@DEF CON ChinaTriton and Symbolic execution on GDB@DEF CON China
Triton and Symbolic execution on GDB@DEF CON China
 
Celery: The Distributed Task Queue
Celery: The Distributed Task QueueCelery: The Distributed Task Queue
Celery: The Distributed Task Queue
 
Testing – With Mock Objects
Testing – With Mock ObjectsTesting – With Mock Objects
Testing – With Mock Objects
 
Lifecycle of a JIT compiled code
Lifecycle of a JIT compiled codeLifecycle of a JIT compiled code
Lifecycle of a JIT compiled code
 
C-Sharp 6.0 ver2
C-Sharp 6.0 ver2C-Sharp 6.0 ver2
C-Sharp 6.0 ver2
 
OrigoDB - take the red pill
OrigoDB - take the red pillOrigoDB - take the red pill
OrigoDB - take the red pill
 
Raffaele Rialdi
Raffaele RialdiRaffaele Rialdi
Raffaele Rialdi
 
Invoke dynamic your api to hotspot
Invoke dynamic your api to hotspotInvoke dynamic your api to hotspot
Invoke dynamic your api to hotspot
 
What's a macro?: Learning by Examples
What's a macro?: Learning by ExamplesWhat's a macro?: Learning by Examples
What's a macro?: Learning by Examples
 
Lecture from javaday.bg by Nayden Gochev/ Ivan Ivanov and Mitia Alexandrov
Lecture from javaday.bg by Nayden Gochev/ Ivan Ivanov and Mitia Alexandrov Lecture from javaday.bg by Nayden Gochev/ Ivan Ivanov and Mitia Alexandrov
Lecture from javaday.bg by Nayden Gochev/ Ivan Ivanov and Mitia Alexandrov
 

Plus de Koichi Sakata

Guide to GraalVM (JJUG CCC 2019 Fall)
Guide to GraalVM (JJUG CCC 2019 Fall)Guide to GraalVM (JJUG CCC 2019 Fall)
Guide to GraalVM (JJUG CCC 2019 Fall)
Koichi Sakata
 
GraalVMで使われている、他言語をJVM上に実装する仕組みを学ぼう
GraalVMで使われている、他言語をJVM上に実装する仕組みを学ぼうGraalVMで使われている、他言語をJVM上に実装する仕組みを学ぼう
GraalVMで使われている、他言語をJVM上に実装する仕組みを学ぼう
Koichi Sakata
 
KanJava 201804 Career 思い込みから逃れた先には、可能性がある
KanJava 201804 Career 思い込みから逃れた先には、可能性があるKanJava 201804 Career 思い込みから逃れた先には、可能性がある
KanJava 201804 Career 思い込みから逃れた先には、可能性がある
Koichi Sakata
 
JJUG CCC 2017 Spring Seasar2からSpringへ移行した俺たちのアプリケーションがマイクロサービスアーキテクチャへ歩み始めた
JJUG CCC 2017 Spring Seasar2からSpringへ移行した俺たちのアプリケーションがマイクロサービスアーキテクチャへ歩み始めたJJUG CCC 2017 Spring Seasar2からSpringへ移行した俺たちのアプリケーションがマイクロサービスアーキテクチャへ歩み始めた
JJUG CCC 2017 Spring Seasar2からSpringへ移行した俺たちのアプリケーションがマイクロサービスアーキテクチャへ歩み始めた
Koichi Sakata
 
Seasar2で作った俺たちのサービスの今
Seasar2で作った俺たちのサービスの今Seasar2で作った俺たちのサービスの今
Seasar2で作った俺たちのサービスの今
Koichi Sakata
 

Plus de Koichi Sakata (20)

Introduction to JIT Compiler in JVM
Introduction to JIT Compiler in JVMIntroduction to JIT Compiler in JVM
Introduction to JIT Compiler in JVM
 
Guide to GraalVM (Oracle Groundbreakers APAC 2019 Tour in Tokyo)
Guide to GraalVM (Oracle Groundbreakers APAC 2019 Tour in Tokyo)Guide to GraalVM (Oracle Groundbreakers APAC 2019 Tour in Tokyo)
Guide to GraalVM (Oracle Groundbreakers APAC 2019 Tour in Tokyo)
 
Guide to GraalVM (JJUG CCC 2019 Fall)
Guide to GraalVM (JJUG CCC 2019 Fall)Guide to GraalVM (JJUG CCC 2019 Fall)
Guide to GraalVM (JJUG CCC 2019 Fall)
 
Introduction to GraalVM and Native Image
Introduction to GraalVM and Native ImageIntroduction to GraalVM and Native Image
Introduction to GraalVM and Native Image
 
Introduction to GraalVM
Introduction to GraalVMIntroduction to GraalVM
Introduction to GraalVM
 
GraalVMで使われている、他言語をJVM上に実装する仕組みを学ぼう
GraalVMで使われている、他言語をJVM上に実装する仕組みを学ぼうGraalVMで使われている、他言語をJVM上に実装する仕組みを学ぼう
GraalVMで使われている、他言語をJVM上に実装する仕組みを学ぼう
 
Great Ideas in GraalVM
Great Ideas in GraalVMGreat Ideas in GraalVM
Great Ideas in GraalVM
 
Graal in GraalVM - A New JIT Compiler
Graal in GraalVM - A New JIT CompilerGraal in GraalVM - A New JIT Compiler
Graal in GraalVM - A New JIT Compiler
 
Kanjava 201804 Java News
Kanjava 201804 Java NewsKanjava 201804 Java News
Kanjava 201804 Java News
 
KanJava 201804 Career 思い込みから逃れた先には、可能性がある
KanJava 201804 Career 思い込みから逃れた先には、可能性があるKanJava 201804 Career 思い込みから逃れた先には、可能性がある
KanJava 201804 Career 思い込みから逃れた先には、可能性がある
 
from Java EE to Jakarta EE
from Java EE to Jakarta EEfrom Java EE to Jakarta EE
from Java EE to Jakarta EE
 
Java release cadence has been changed and about Project Amber
Java release cadence has been changed and about Project AmberJava release cadence has been changed and about Project Amber
Java release cadence has been changed and about Project Amber
 
JJUG CCC 2017 Fall オレオレJVM言語を作ってみる
JJUG CCC 2017 Fall オレオレJVM言語を作ってみるJJUG CCC 2017 Fall オレオレJVM言語を作ってみる
JJUG CCC 2017 Fall オレオレJVM言語を作ってみる
 
KANJAVA PARTY 2017 前説
KANJAVA PARTY 2017 前説KANJAVA PARTY 2017 前説
KANJAVA PARTY 2017 前説
 
JJUG CCC 2017 Spring Seasar2からSpringへ移行した俺たちのアプリケーションがマイクロサービスアーキテクチャへ歩み始めた
JJUG CCC 2017 Spring Seasar2からSpringへ移行した俺たちのアプリケーションがマイクロサービスアーキテクチャへ歩み始めたJJUG CCC 2017 Spring Seasar2からSpringへ移行した俺たちのアプリケーションがマイクロサービスアーキテクチャへ歩み始めた
JJUG CCC 2017 Spring Seasar2からSpringへ移行した俺たちのアプリケーションがマイクロサービスアーキテクチャへ歩み始めた
 
“Purikura” culture in Japan and our web application architecture
“Purikura” culturein Japan andour web application architecture“Purikura” culturein Japan andour web application architecture
“Purikura” culture in Japan and our web application architecture
 
デブサミ2017 Javaコミュニティ作ったら人生変わった
デブサミ2017 Javaコミュニティ作ったら人生変わったデブサミ2017 Javaコミュニティ作ったら人生変わった
デブサミ2017 Javaコミュニティ作ったら人生変わった
 
JJUG CCC 2016 fall バイトコードが君のトモダチになりたがっている
JJUG CCC 2016 fall バイトコードが君のトモダチになりたがっているJJUG CCC 2016 fall バイトコードが君のトモダチになりたがっている
JJUG CCC 2016 fall バイトコードが君のトモダチになりたがっている
 
日本からJavaOneに行こう!
日本からJavaOneに行こう!日本からJavaOneに行こう!
日本からJavaOneに行こう!
 
Seasar2で作った俺たちのサービスの今
Seasar2で作った俺たちのサービスの今Seasar2で作った俺たちのサービスの今
Seasar2で作った俺たちのサービスの今
 

Dernier

Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Victor Rentea
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Safe Software
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Victor Rentea
 

Dernier (20)

Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistan
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024
 
Understanding the FAA Part 107 License ..
Understanding the FAA Part 107 License ..Understanding the FAA Part 107 License ..
Understanding the FAA Part 107 License ..
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
 
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
 
Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
 
Exploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusExploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with Milvus
 
Six Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal OntologySix Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal Ontology
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 

Bytecode Manipulation with a Java Agent and Byte Buddy

Notes de l'éditeur

  1. Hello, everyone! Today, I'd like to talk about manipulating Java bytecode. I'll introduce Java Agent and a library called Byte Buddy.
  2. Let me briefly introduce myself. I'm Koichi Sakata. I'm a KanJava JUG leader. Kan means Kansai region in Japan. It includes Kyoto. Do you know Kyoto? Kyoto is visited by many tourists. I became a Java champion this year. I work at PONOS Corporation, that is a mobile game company.
  3. This session is for beginners, not for experts.
  4. Moving on to our main topic. Java bytecode is generated by the javac compiler. It's in a class file. It's an intermediate representation of Java programs. We can visualize bytecode with javap command.
  5. What is bytecode manipulation? It's to edit bytecode, such as add, delete and replace bytecode.
  6. Why do we manipulate bytecode? Because it's fun!
  7. But not only fun. It's also useful to change code at runtime. For example, Hibernate uses bytecode manipulation to generate entity objects, and Mockito uses it to create mock objects. Of course at runtime.
  8. It's hard to change bytecode by hand. Because a class file is a binary file and JVM has a verification process for a class file.
  9. So there are many libraries for bytecode manipulation. Byte Buddy, Byteman, Javassist, cglib, ASM and BCEL. Today I'll introduce Byte Buddy.
  10. Why Byte Buddy? Byte Buddy has a Easy-to-use API, supports Java 11 already and won a Duke's Choice Award.
  11. Many major libraries are using Byte Buddy, such as Hibernate, Mockito, Jackson, etc.
  12. This is a hello world program with Byte Buddy. It creates a new class that extends Object class, and overrides toString() method to return "Hello World". I'll explain the details of this code.
  13. First, we create a subclass of the Object class and choose the toString() method.
  14. Next, we intercept the metod to return a fixed string value "Hello World".
  15. Make method builds a new type. The new type isn't loaded by a classloader yet, so the type is an unloaded class. Then the classloader loads the type. Finally we can get the new loaded class object. It's easy to manipulate bytecode with Byte Buddy. That's the reason why Byte Buddy is so popular.
  16. OK, I explained all parts of this code.
  17. Let's run the hello world. This code is a bit different from the previous code. I'll save a generated class to a file and outputs the method return. (run HelloWorld) Let's see the generated file. It is in a temp directory. Byte Buddy names the dynamic class randomly.
  18. By the way, the demo code used today is available on GitHub. Just access "bitly/oc1bcm"
  19. Now I'd like to show code in Mockito. Mockito is a famous mocking framework. This method creates a mock class. As you can see, it's similar to our hello world example.
  20. How to use? You can run bytecode manipulation code directly in your application. But you need to change your code. When you choose the second option, you need to rebuild. So I'd like to introduce Java Agent. It doesn't require the change. It's also detachable.
  21. What is Java Agent? The word "Agent" invokes the "Mission: Impossible" spy series. Java Agent do espionage activities in your application, like profiling, logging and even changing the behavior of the application itself.
  22. Java Agent can instrument programs running on the JVM. It's defined as JSR 163. The JVM calls Java Agent methods with proper timing.
  23. To create a Java Agent, just define one of the these methods or both, premain() and agentmain().
  24. Premain() method is called by the JVM before the application's main method(). Agentmain() is called when the agent is attached after the JVM has started.
  25. So with Java Agent, we can run bytecode manipulation code at runtime.
  26. To create a Java Agent, first, define the Agent Class method. Second, write a MANIFEST.MF file. Third, package the Agent class to a JAR file. Finally, run java command with javaagent option.
  27. A signature of premain() is "public static void premain()". We can have an opportunity to modify classes before the class is loaded. Instrumentation class in method parameters provides useful methods to modify classes.
  28. In the manifest file, we specify the Agent class and set the path to the Byte Buddy's JAR file.
  29. Let's create a simple Java Agent. The Agent class is a Java agent class. It has the premain() method. This is the Main class. Run the main() method with javaagent option. As you can see, premain() executed before main method.
  30. Let's combine Java Agent with Byte Buddy. I'll show another example. It adds outputting logs before executing a particular method on a particular class.
  31. I'll do two things. First, define the premain() method in a class. Second, write code in premain() method to replace the class file to output a log. Note that I don't create a subclass.
  32. This is the Target class. We want to output a log when foo() method is called.
  33. Next, replace the class with Byte Buddy. Let me explain the details of this code.
  34. This code uses rebase() method, instead of previous subclass() method. Rebase() method doesn't create a subclass. It replaces the original implementation with new one and saves it under a different method name.
  35. Byte Buddy provides three method to enhance existing methods. Subclass() creates a subclass and overrides the method. Redefine() replaces the implementation with new one. Rebase() also replaces it and saves the original implementation.
  36. Note that we can't use a class literal. If we use a class literal for the Target class, the JVM will load the class before changing the class. We can use the TypePool class and its describe() method, to represent the class without the class literal.
  37. Also, note that when using unloaded classes, we need to specify a ClassFileLocator. It allows to locate a class file. In this example, we simply create a class file locator with ofClassPath() method. It scans the running application's class path for class files.
  38. This time I'd like to delegate outputting to another class, LoggingInterceptor class.
  39. To do so, We can use MethodDelegation.to() method. We simply specify a class to delegate. A best match method is chosen automatically by Byte Buddy.
  40. After the method is invoked, the original call will continue, thanks to andThen() method with SuperMethodCall.INSTANCE. SuperMethodCall.INSTANCE represents the original method.
  41. This is the interceptor class. This code outputs the intecepted method name.
  42. In delegated method, various annotations can be used. The Origin annotation is a reference to the original method or constructor. So we can get the method object of the original method.
  43. Other annotations are shown here. More details can be found in the Byte Buddy's website.
  44. Go back to the premain(). How do we run that code in Java Agent? Instrument API provides ClassFileTransformer class to change bytecode. To manipulate bytecode in Java Agent, We need to override transform(). Then pass the ClassFileTransformer instance to addTransformer() of the Instrumentation class. The transform() will be called by the JVM before loading.
  45. Let's go on to the transform() method. We can call the manipulation code in transform() method.
  46. In parameters, class name is the name to be loaded. Class file buffer is the content of the class file.
  47. We return the class file content from the transform().
  48. Finally we can run the demo. Let's see the complete code. (Show LoggingAgent class) (run Target class) OK, foo() is intercepted.
  49. So we covered the basics of Byte Buddy and Java Agent.
  50. Of course, there are many features in Byte Buddy. Add fields and methods, manipulate even stacks. Also, we can generate CONDY code with Byte Buddy. Have you ever heard about condy? CONDY means constant dynamic. It defines as JEP 309. It's included from Java 11, but the Java compiler doesn't use CONDY yet. We can try to use CONDY directly with Byte Buddy.
  51. Acutually Byte Buddy provides AgentBuilder class to simplify Java Agent. We can rewrite the previous Logging Agent with AgentBuilder.
  52. Just use AgentBuilder class instead of ByteBuddy class, and use AgentBuilder.Transformer instead of ClassFileTransformer. Call install() method at the end.
  53. Use AgentBuilder, Use AgentBuilder.Transformer and call installOn().
  54. Then We can use builder object to intercept the method. Let's see the complete code. (show LoggingAgent class) This code is more readable, isn't it? (mvn package & run Target class)
  55. Additionally, when we use AgentBuilder, we can remove javaagent option. Just call ByteBuddyAgent's install() and AgentBuilder's installOnByteBuddyAgent() instead of installOn() method. To use ByteBuddyAgent, we need to add byte-buddy-agent JAR file to the class path.
  56. Call ByteBuddyAgent.install() and AgentBuidler's installOnByteBuddyAgent().
  57. (show LoggingMainWithoutAgent class) Run this code without javaagent option. (run LoggingMainWithoutAgent)
  58. Let's wrap up. Bytecode manipulation is fun, and it's close to us. I'd like to stress this point. Many famous libraries are using bytecode manipulation. As application examples, there are How Swap, which swap classes at runtime, and advanced dynamic proxy.