Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Java Debugging Internals
Search
Yarden Laifenfeld
November 22, 2022
Programming
190
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Java Debugging Internals
Yarden Laifenfeld
November 22, 2022
More Decks by Yarden Laifenfeld
See All by Yarden Laifenfeld
When Bits Hit the TurboFan
yardenlaif
0
290
OpenFeature: The Future of Feature Flags
yardenlaif
0
220
Go Sync or Go Home: Advanced Concurrency Techniques for Better Go Programs
yardenlaif
0
250
Go Stack: Should it be Moving Like That?
yardenlaif
0
230
Java Debugging Internals - JPrime 2023
yardenlaif
0
170
Debugging, the Developer Way
yardenlaif
0
270
Ruby & JVM: A (JRuby) Love Story - RubyConfTh
yardenlaif
0
240
Ruby & JVM: A (JRuby) Love Story
yardenlaif
0
330
Other Decks in Programming
See All in Programming
RAG の “R” を Swift で覗いてみる 〜「意味から探す」検索の仕組み〜
nao_randd
0
120
Atomic Design, Enforced: Scaling Mobile Design Systems (next.app devCon / droidCon Berlin 2026)
steliosf
PRO
0
130
コードレビューのボトルネックを"する側"と"される側"の両面から解消する
yub0n
2
1.5k
動作中のプログラムの中身をリアルタイムに覗く / Realtime Debugger for CSharp with Roslyn
prota
1
1.8k
AI時代のコードレビューは人に向けるな、仕組みに向けろ
texmeijin
5
3.5k
When benchmarks go bad - what I learned from measuring performance wrong
hollycummins
0
160
モバイル交通系ICへのチャージ実例から考える、クロスプラットフォーム開発におけるiOS実機テスト設計とCI運用
yusuga
1
580
スマートフォンでモールス信号を送受信する 〜スマートフォンのLEDとカメラで作る光通信の設計と実装〜
atsuki_seo
0
230
Verilogで学ぶCPU自作入門.pdf
uyuki234
8
4k
なぜCTOを降りてFDEを選んだのか?〜なぜプロダクト企業がFDEで顧客の現場に踏み込むのか〜
gonta
1
160
速習iPhone Duo対応
yuukiw00w
2
960
AIに “答え“を書かせるのを やめてみた
___akari11
0
110
Featured
See All Featured
Fantastic passwords and where to find them - at NoRuKo
philnash
52
4k
Optimizing for Happiness
mojombo
378
71k
Put a Button on it: Removing Barriers to Going Fast.
kastner
60
4.6k
SEO in 2025: How to Prepare for the Future of Search
ipullrank
3
3.9k
How to build an LLM SEO readiness audit: a practical framework
nmsamuel
2
930
AI Search: Implications for SEO and How to Move Forward - #ShenzhenSEOConference
aleyda
1
1.4k
Balancing Empowerment & Direction
lara
6
1.3k
Product Roadmaps are Hard
iamctodd
55
13k
Visual Storytelling: How to be a Superhuman Communicator
reverentgeek
2
700
GraphQLとの向き合い方2022年版
quramy
50
15k
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
46
3k
Mind Mapping
helmedeiros
1
390
Transcript
Java Debugging Internals @yardenlaif
2 Who Am I? • Software Engineer at Rookout •
Background in low level C programming in linux IOT environments • Java, Go, Ruby • C#, Python, JavaScript, C++
Non Breaking Breakpoints 3
Non Breaking Breakpoints 4
jdb -attach 8000 java -agentlib:jdwp= transport=dt_socket,server=y, suspend=n,address=*:8000 myApp JDB -
The Java Debugger 5 JVM MyApp Debugger CLI
JPDA - Java Platform Debugging Architecture The Java Platform Debugger
Architecture (JPDA) consists of three interfaces designed for use by debuggers in development environments for desktop systems. - Oracle Documentation 6
JPDA - Java Platform Debugging Architecture • JDI - Java
Debug Interface • JDWP - Java Debug Wire Protocol • JVMTI - Java Virtual Machine Tool Interface 7
JDI - Java Debug Interface • High level Java API
• Inspect & Control • Connect remotely 8
JDI - Java Debug Interface • Add breakpoint ◦ createBreakpointRequest
• Collect data ◦ visibleVariables ◦ getArgumentValues ◦ frames • Continue program ◦ resume 9
Using JDI • No availability during collection • Zero control
or visibility • Easy to make mistakes • Single instance debugging 10
JPDA - Java Platform Debugging Architecture • JDI - Java
Debug Interface • JDWP - Java Debug Wire Protocol • JVMTI - Java Virtual Machine Tool Interface 11
JDWP - Java Debug Wire Protocol • A protocol •
Used for communication between a debugger and the JVM which it debugs 12 JVM MyApp Debugger CLI JDWP
Using JDWP • No availability during collection • Zero control
or visibility • Easy to make mistakes • Single instance debugging • Managing multiple clients and connecting to multiple servers 13
JPDA - Java Platform Debugging Architecture • JDI - Java
Debug Interface • JDWP - Java Debug Wire Protocol • JVMTI - Java Virtual Machine Tool Interface 14
JVMTI - Java Virtual Machine Tool Interface • Native programming
interface • Interacts directly with the JVM • Inspect & Control 15
JVMTI - Java Virtual Machine Tool Interface • SetBreakpoint •
SetEventNotificationMode ◦ Breakpoint • GetLocalObject ◦ jobject 16
JVMTI - Get Stack Trace /* Get Stack Trace */
err = (*jvmti)->GetStackTrace(jvmti, thr, 0, 5, &frames, &count); if (err != JVMTI_ERROR_NONE) { printf("(GetThreadInfo) Error expected: %d, got: %d\n", JVMTI_ERROR_NONE, err); describe(err); printf("\n"); } printf("Number of records filled: %d\n", count); if (err == JVMTI_ERROR_NONE && count >=1) { char *methodName; methodName = "yet_to_call()"; char *declaringClassName; jclass declaring_class; int i=0; printf("Exception Stack Trace\n"); printf("=====================\n"); printf("Stack Trace Depth: %d\n", count); for ( i=0; i < count; i++) { err = (*jvmti)->GetMethodName(jvmti, frames[i].method, &methodName, NULL, NULL); if (err == JVMTI_ERROR_NONE) { err = (*jvmti)->GetMethodDeclaringClass(jvmti, frames[i].method, &declaring_class); err = (*jvmti)->GetClassSignature(jvmti, declaring_class, &declaringClassName, NULL); if (err == JVMTI_ERROR_NONE) { printf("at method %s() in class %s\n", methodName, declaringClassName); } } } } 17 *A lot of code*
Java - Get Stack Trace Thread.currentThread().getStackTrace() 18
Using JVMTI • Incredibly Complex • Native vulnerabilities • Not
portable • Bugs are catastrophic 19
20 Newer? Simpler? Full control? In-process? Unbreakable?
Requirements 21 • Don’t break • Predictability • Availability •
Performance • Security and compliance • Multi-instance debugging
Thread 2: Client Connection public Response Process(Request req) { String
id = req.GetID(); if (isExistingUser(id)) { return new Response("User exists!"); } // Create new user... } Requirements 22 • Don’t break • Availability Thread 1: Server Client Connection Thread 3: Client Connection public Response Process(Request req) { String id = req.GetID(); if (isExistingUser(id)) { return new Response("User exists!"); } // Create new user... } Thread 2: Client Connection public Response Process(Request req) { String id = req.GetID(); if (isExistingUser(id)) { return new Response("User exists!"); } // Create new user... }
-agentlib:jdwp address=*:8000 transport=dt_socket server=y suspend=n Break It Down java -agentlib:jdwp=transport=dt_socket,server=y,
suspend=n,address=*:8000 myApp 23
Java Agents 24
Java Agents 25 JVM MyApp Java Agent java.lang.Instrument API
Sample Program 26 1| public class HelloWorld { 2| public
static void main(String[] args) { 3| while(true) { 4| System.out.println("Hello, World!"); 5| } 6| } 7| }
Sample Program 27 • Build HelloWorld to JAR • Run:
java -jar HelloWorld.jar • Output: Hello, World! Hello, World! ...
Java Agent - Premain 28 public class JavaAgent { public
static void premain(String agentArgs, Instrumentation instrumentation) throws Exception { System.out.println("Hello, JavaSummit!"); } }
Java Agent - Premain 29 public class JavaAgent { public
static void premain(String agentArgs, Instrumentation instrumentation) throws Exception { System.out.println("Hello, JavaSummit!"); } }
Java Agent - Premain 30 public class JavaAgent { public
static void premain(String agentArgs, Instrumentation instrumentation) throws Exception { System.out.println("Hello, JavaSummit!"); } }
Java Agent - Premain 31 public class JavaAgent { public
static void premain(String agentArgs, Instrumentation instrumentation) throws Exception { System.out.println("Hello, JavaSummit!"); } }
Java Agent - Premain 32 • Build JavaAgent to JAR
• Run with java agent: java -javaagent:JavaAgent.jar -jar HelloWorld.jar • Output: Hello, JavaSummit! Hello, World! ...
Java Agent - ClassFileTransformer 33 JVM Compiler Code Bytecode
Java Agent - ClassFileTransformer 34 JVM 32 | … 33
| new Item() 34 | … Class Loader Get Item class bytecode Return Item class bytecode
Java Agent - ClassFileTransformer 35 JVM 32 | … 33
| new Item() 34 | … Class Loader Get Item class bytecode Return Item class bytecode Class File Transformer Return transformed Item class bytecode
Java Agent - ClassFileTransformer 36 public class JavaAgent { public
static void premain(String agentArgs, Instrumentation instrumentation) throws Exception { System.out.println("Hello, JavaSummit!"); } } • void addTransformer(ClassFileTransformer transformer);
Java Agent - ClassFileTransformer 37 public class DebugTransformer implements ClassFileTransformer
{ @Override public byte[] transform(ClassLoader classLoader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) {
Java Agent - ClassFileTransformer 38 public class DebugTransformer implements ClassFileTransformer
{ @Override public byte[] transform(ClassLoader classLoader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) {
Java Agent - ClassFileTransformer 39 public class DebugTransformer implements ClassFileTransformer
{ @Override public byte[] transform(ClassLoader classLoader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) {
Open Source Bytecode Manipulation Tools BCEL ASM 40
Bytecode Abstraction 41 • AbstractInsnNode ◦ JumpInsnNode ◦ MethodInsnNode ◦
VarInsnNode • InsnList instructions
Bytecode Manipulation 42 byte[] addPrintCall(byte[] classfileBuffer) { // Add call
to System.out.println("Transformed!") // Return transformed bytecode }
Java Agent - ClassFileTransformer 43 public class DebugTransformer implements ClassFileTransformer
{ @Override public byte[] transform(ClassLoader classLoader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) { if (className.contains("HelloWorld")) { return addPrintCall(classfileBuffer); } return classfileBuffer; } }
Java Agent - ClassFileTransformer 44 public class DebugTransformer implements ClassFileTransformer
{ @Override public byte[] transform(ClassLoader classLoader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) { if (className.contains("HelloWorld")) { return addPrintCall(classfileBuffer); } return classfileBuffer; } }
Java Agent - Premain 45 public class JavaAgent { public
static void premain(String agentArgs, Instrumentation instrumentation) throws Exception { DebugTransformer transformer = new DebugTransformer(); instrumentation.addTransformer(transformer); } }
Java Agent - Premain 46 public class JavaAgent { public
static void premain(String agentArgs, Instrumentation instrumentation) throws Exception { DebugTransformer transformer = new DebugTransformer(); instrumentation.addTransformer(transformer); } }
Java Agent - Premain 47 • Build JavaAgent to JAR
• Run with java agent: java -javaagent:JavaAgent.jar -jar HelloWorld.jar • Output: Transformed! Hello, World! Hello, World! ...
Non-Breaking Breakpoints!
Profiling Interpreter C2 C1 Profiling Profiling Interpreter C2 C1 Profiling
JVM Execution Engine 49
Add Breakpoint 50 public void Breakpoint(Object[] locals) { System.out.println("Breakpoint hit!");
for (Object local : locals) { System.out.println(local); } }
Add Breakpoint 51 byte[] addBreakpoint(byte[] classfileBuffer, int lineno) { //
Find where to insert Breakpoint call // Push local variables onto stack // Insert call to Breakpoint // Return transformed bytecode }
Add Breakpoint 52 byte[] addBreakpoint(byte[] classfileBuffer, int lineno) { //
Find where to insert Breakpoint call // Push local variables onto stack // Insert call to Breakpoint // Return transformed bytecode }
Add Breakpoint 53 byte[] addBreakpoint(byte[] classfileBuffer, int lineno) { //
Find where to insert Breakpoint call // Push local variables onto stack // Insert call to Breakpoint // Return transformed bytecode }
Add Breakpoint 54 byte[] addBreakpoint(byte[] classfileBuffer, int lineno) { //
Find where to insert Breakpoint call // Push local variables onto stack // Insert call to Breakpoint // Return transformed bytecode }
Add Breakpoint 55 byte[] addBreakpoint(byte[] classfileBuffer, int lineno) { //
Find where to insert Breakpoint call // Push local variables onto stack // Insert call to Breakpoint // Return transformed bytecode }
Sample Program 56 1| public class HelloWorld { 2| public
static void main(String[] args) { 3| while(true) { 4| System.out.println("Hello, World!"); 5| } 6| } 7| }
Java Agent - ClassFileTransformer 57 public class DebugTransformer implements ClassFileTransformer
{ @Override public byte[] transform(ClassLoader classLoader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) { if (className.contains("HelloWorld")) { return addBreakpoint(classfileBuffer, 4); } return classfileBuffer; } }
Java Agent - Premain 58 • Build JavaAgent to JAR
• Run with java agent: java -javaagent:JavaAgent.jar -jar HelloWorld.jar • Output: Breakpoint hit! [Ljava.lang.Object;@3d075dc0 Hello, World! ...
59 What if the class has already been loaded?
Magic Instrumentation 60 void redefineClasses(ClassDefinition... definitions) void retransformClasses(Class<?>... classes)
Putting it all together 61 • Transform on demand •
Add call to breakpoint function • Access locals as objects
62 Putting it all together
Thank You @yardenlaif rookout.com