Skip to main content
© 2025 NTT DATA Japan Corporation
© 2025 NTT DATA Japan Corporation
Unveiling the Hidden Layers of Java Class
Files: Beyond Bytecode
Mar. 6th, 2025
NTT DATA Group Corporation
Koichi Sakata
© 2025 NTT DATA Japan Corporation 2
About Me
Koichi SAKATA (阪田 浩一)
Java Champion
OpenJDK Committer
jyukutyo
© 2025 NTT DATA Japan Corporation
© 2025 NTT DATA Japan Corporation 3
ClassFile Crash Course
3
© 2025 NTT DATA Japan Corporation 4
ClassFile
void main() {
println("He
}
0101010101010
0101010101010
0101010101010
0101010101010
0101010101010
Compiling with the javac Command
Source File
Class File
• Bytecode
• Constant Pool
• and so on.
© 2025 NTT DATA Japan Corporation 5
ClassFile
0101010101010
Class File
cafe babe 0000 0034 001d 0a00 0600
0f09 0010 0011 0800 120a 0013 0014
0700 1507 0016 0100 063c 696e 6974
3e01 0003 2829 5601 0004 436f 6465
0100 0f4c 696e 654e 756d 6265 7254
...
Open in Hex Format
in Binary
Format
© 2025 NTT DATA Japan Corporation 6
ClassFile
https://blog.lse.epita.fr/2014/04/28/0xcafebabe-java-class-file-format-an-overview.html
© 2025 NTT DATA Japan Corporation 7
Attributes in Class Files
• Stores information related to classes, fields, and methods
- Code
- Local variables
- Constant values
- Stack
- Exceptions
- Inner classes
- Bootstrap methods
- Annotations
- Deprecated methods
- Signatures
© 2025 NTT DATA Japan Corporation 8
Disassemble with the javap Command
0101010101010
ClassFile
cafe babe 0000 0034 001d 0a00 0600
0f09 0010 0011 0800 120a 0013 0014
0700 1507 0016 0100 063c 696e 6974
3e01 0003 2829 5601 0004 436f 6465
0100 0f4c 696e 654e 756d 6265 7254
...
javap -c HelloWorld
class HelloWorld {
HelloWorld();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String...);
Code:
0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #3 // String Hello, world!
5: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
© 2025 NTT DATA Japan Corporation 9
javap Command Options
• Common Option: -c (Usually sufficient)
• Detailed Information: -v (Displays additional details)
• List of Options: -help (Shows all available options)
© 2025 NTT DATA Japan Corporation
© 2025 NTT DATA Japan Corporation 10
Reason and Purpose
1
© 2025 NTT DATA Japan Corporation 11
Reason and Purpose of Discussing Class Files
• Why Class Files?
- Understanding the internals of class files is key for in-depth Java
knowledge.
- It may not be immediately necessary, but it's fascinating topic for
developers
• Passion for the Topic
- Enjoy discussing class files and their intricacies.
- Organized this session to delve into more than just bytecode.
• Goals for the Session
- Highlight other interesting aspects of class files.
- Encourage hands-on practice of the concepts covered today.
© 2025 NTT DATA Japan Corporation
© 2025 NTT DATA Japan Corporation 12
Source Files and Class Files
1
© 2025 NTT DATA Japan Corporation 13
Source Files vs. Class Files
• Role of the Java Compiler
- Ensures the conversion is accurate and aligns both specifications.
void main()
println("
}
CAFEBABE
Source File Class File
Java Compiler
Files Specification
Source Files The Java Language Specification(JLS)
Class Files The Java Virtual Machine Specification(JVMS)
© 2025 NTT DATA Japan Corporation 14
Java Compiler Operations to Keep in Mind
• Creating Additional Methods
- Compiler may add its own methods to the class files
(excluding default constructor)
• Differences in Class Files
- Generated class files content can vary by JDK version, even with the
same source files.
© 2025 NTT DATA Japan Corporation
© 2025 NTT DATA Japan Corporation 15
Compiler-Created Methods
1
© 2025 NTT DATA Japan Corporation 16
Methods Created by the Compiler
• Reason for Compiler-Created Methods
- Differences between Java Language Specification (JLS) and
Java Virtual Machine Specification (JVMS).
- Necessary to accurately represent Java code as class files.
• Synthetic Methods
- Additional methods created by the compiler.
- Used to bridge the gap between bytecodes' simple structure and
Java's rich expressiveness.
© 2025 NTT DATA Japan Corporation 17
Synthetic Method Example
• Covariant Return Type
public interface ReturnNumber {
Number value();
}
public class ReturnInteger implements ReturnNumber {
public Integer value() {
return Integer.valueOf(0);
}
}
© 2025 NTT DATA Japan Corporation 18
Synthetic Method
• $ javap -c ReturnInteger
class ReturnInteger implements ReturnNumber {
public java.lang.Integer value();
Code:
0: iconst_0
1: invokestatic #7 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
4: areturn
public java.lang.Number value();
Code:
0: aload_0
1: invokevirtual #13 // Method value:()Ljava/lang/Integer;
4: areturn
© 2025 NTT DATA Japan Corporation 19
Bytecode Instructions for Method Calls
• 5 Types of invoke Instructions
Code:
1: invokestatic #7 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
...
1: invokevirtual #13 // Method value:()Ljava/lang/Integer;
Bytecode Content
invokestatic Static Method call
invokevirtual Instance Method call
invokespecial Constructor, Private, and Super Class Method Call
invokeinterface Interface Method Call
invokedynamic Dynamic Method Call (Described Later)
© 2025 NTT DATA Japan Corporation 20
Synthetic Method
• $ javap -c ReturnInteger
class ReturnInteger implements ReturnNumber {
public java.lang.Integer value();
Code:
0: iconst_0
1: invokestatic #7 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
4: areturn
public java.lang.Number value();
Code:
0: aload_0
1: invokevirtual #13 // Method value:()Ljava/lang/Integer;
4: areturn
© 2025 NTT DATA Japan Corporation 21
Synthetic Method
• $ javap -v ReturnInteger
public java.lang.Number value();
descriptor: ()Ljava/lang/Number;
flags: ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokevirtual #13 // Method value:()Ljava/lang/Integer;
4: areturn
• Synthetic Method: A method created by the compiler
• Bridge Method: A synthetic method to handle
differences between method definitions
Synthetic
Method
Bridge
Method
© 2025 NTT DATA Japan Corporation
© 2025 NTT DATA Japan Corporation 22
Synthetic Methods and Inner Classes
2
© 2025 NTT DATA Japan Corporation 23
Synthetic Methods and Inner Classes
• Creation of Synthetic Methods
‒ The compiler creates and writes synthetic methods for certain code.
• Inner Classes
‒ Inner classes can have synthetic methods generated.
‒ JDK 10 and Earlier: Synthetic methods were commonly generated for
inner classes.
‒ JDK 11 and Later: Changes in class file content.
© 2025 NTT DATA Japan Corporation 24
What is an Inner Class?
public class Outer {
class Inner {
}
public static void main(String[] args) {
// Write the following to create an instance of the Inner class
new Outer().new Inner();
}
}
© 2025 NTT DATA Japan Corporation 25
Example of a Synthetic Method
public class Outer {
private void m_outerpriv() {
System.out.println("called m_outerpriv");
}
class Inner {
public void test() {
new Outer().m_outerpriv();
}
}
public static void main(String[] args) {
new Outer().new Inner().test();
}
}
• Inner Class Accessing Private Members[1]
[1] https://docs.oracle.com/javase/specs/jls/se23/html/jls-6.html#jls-6.6.1
Execution Flow
© 2025 NTT DATA Japan Corporation 26
Synthetic Method Example in JDK 10
class Outer$Inner {
...
public void test();
Code:
0: new #3 // class Outer
3: dup
4: invokespecial #4 // Method Outer."<init>":()V
7: invokestatic #5 // Method Outer.access$000:(LOuter;)V
10: return
}
• $ javap -c Outer¥$Inner
Where did the call to
new Outer().m_outerpriv() go?
© 2025 NTT DATA Japan Corporation 27
Class File Compiled with JDK 10
public class Outer {
...
static void access$000(Outer);
descriptor: (LOuter;)V
flags: ACC_STATIC, ACC_SYNTHETIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method m_outerpriv:()V
4: return
}
• $ javap -v Outer
SYNTHETIC
but not BRIDGE
© 2025 NTT DATA Japan Corporation 28
Synthetic Methods in JDK 10 and Before
In Inter class:
Source File Class File
Call the private method, m_outerpriv(),
in the Outer instance.
Call the static method,
Outer.access$000(Outer)
In Outer class:
• The compiler created a static synthetic method,
access$000(Outer).
• In the access$000 method, call m_outerpriv() for the Outer
instance of the argument.
© 2025 NTT DATA Japan Corporation 29
Reason for Synthetic Methods
Quoting JVMS $5.4.4 of JDK 10
"A field or method R is accessible to a class or interface D if and only if any
of the following is true:
...
• R is private and is declared in D."
https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-5.html#jvms-5.4.4
The concept of inner classes was not
supported by the JVM specification.
© 2025 NTT DATA Japan Corporation 30
Problems and Changes in Implementation
• Implementation Problems:
‒ Invoking reflection methods from one nested class to another could cause errors.
‒ There are cases where direct lookup is not possible with the Method Handle API.
Therefore, it was decided to change the
nested class specifications in the JVMS.
© 2025 NTT DATA Japan Corporation
© 2025 NTT DATA Japan Corporation 31
Nestmates
3
© 2025 NTT DATA Japan Corporation 32
Changes in JDK 11 for Nested Code
• From JDK 11, the compiler generates different class files for nested code.
$ javap -c Outer¥$Inner(Compiled with JDK 11)
class Outer$Inner {
public void test();
Code:
0: new #7 // class Outer
3: dup
4: invokespecial #9 // Method Outer."<init>":()V
7: invokevirtual #10 // Method Outer.m_outerpriv:()V
10: return
} Synthetic methods in the outer
class were no longer created.
© 2025 NTT DATA Japan Corporation 33
Simplification in JDK 11
• Introduction of Nestmates:
- A concept called nested mates was introduced into the class files.
- New attributes: NestHost and NestMembers.
Host Class Nested Class
Attribute NestMembers NestHost
Class
Nested
Class
NestMembers NestHost
© 2025 NTT DATA Japan Corporation 34
NestHost and NestMembers
$ javap -v Outer
public class Outer
...
NestMembers:
Outer$Inner
$ javap -v Outer¥$Inner
class Outer$Inner
...
NestHost: class Outer
Quoting JVMS $5.4.4 of JDK 23
"A field or method R is accessible to a
class or interface D if and only if any
of the following is true:
...
• R is private and is declared by a
class or interface C that belongs to
the same nest as D, according to
the nestmate test below."
https://docs.oracle.com/javase/specs/jvms/se23/html/jvms-5.html#jvms-5.4.4
© 2025 NTT DATA Japan Corporation 35
Main Point and Insights
• Unchanged Source Code:
- The source code itself hasn't changed.
- "It will work the same way regardless of which JDK version you use to compile.
• User Awareness:
- Users don't need to know these details.
- Understanding these changes and the discussions around them is fascinating.
© 2025 NTT DATA Japan Corporation
© 2025 NTT DATA Japan Corporation 36
Changes in Class File Content and
JVM Improvements
3
© 2025 NTT DATA Japan Corporation 37
Example: String Concatenation
private String
f0="1", f1="1", f2="1", f3="1", f4="1", f5="1", f6="1", f7="1", f8="1", f9="1",
f10="1", f11="1", f12="1", f13="1", f14="1", f15="1", f16="1", f17="1", f18="1", f19="1",
f20="1", f21="1", f22="1", f23="1", f24="1", f25="1", f26="1", f27="1", f28="1", f29="1",
f30="1", f31="1", f32="1", f33="1", f34="1", f35="1", f36="1", f37="1", f38="1", f39="1",
f40="1", f41="1", f42="1", f43="1", f44="1", f45="1", f46="1", f47="1", f48="1", f49="1",
f50="1", f51="1", f52="1", f53="1", f54="1", f55="1", f56="1", f57="1", f58="1", f59="1",
f60="1", f61="1", f62="1", f63="1", f64="1", f65="1", f66="1", f67="1", f68="1", f69="1",
f70="1", f71="1", f72="1", f73="1", f74="1", f75="1", f76="1", f77="1", f78="1", f79="1",
f80="1", f81="1", f82="1", f83="1", f84="1", f85="1", f86="1", f87="1", f88="1", f89="1",
f90="1", f91="1", f92="1", f93="1", f94="1", f95="1", f96="1", f97="1", f98="1", f99="1",
f100="1",f101="1",f102="1",f103="1",f104="1",f105="1",f106="1",f107="1",f108="1",f109="1",
f110="1",f111="1",f112="1",f113="1",f114="1",f115="1",f116="1",f117="1",f118="1",f119="1",
f120="1",f121="1",f122="1";
public String toString() {
return f0+","+ f1+","+ f2+","+ f3+","+ f4+","+ f5+","+ f6+","+ f7+","+ f8+","+ f9+","
+ f10+","+ f11+","+ f12+","+ f13+","+ f14+","+ f15+","+ f16+","+ f17+","+ f18+","
+ ... ","
+f120+","+f121+","+f122;
}
Concatenate 123 Strings
with commas
© 2025 NTT DATA Japan Corporation 38
What happens if you run this code on JDK 22?
public static void main(String[] args) {
long start = System.currentTimeMillis();
long sink = 0L;
while (System.currentTimeMillis() - start < 60000) {
sink += new Test().toString().length();
}
System.out.println(sink);
}
To call the toString() method
multiple times for 60 seconds
© 2025 NTT DATA Japan Corporation 39
What happens if you run this code on JDK 22?
1. Crash during execution
2. Run normally
3. Consume a lot of hardware resources while running
4. Throw an error
public static void main(String[] args) {
long start = System.currentTimeMillis();
long sink = 0L;
while (System.currentTimeMillis() - start < 60000) {
sink += new Test().toString().length();
}
System.out.println(sink);
}
© 2025 NTT DATA Japan Corporation 40
It consumes a lot of memory (3 is correct)
https://bugs.openjdk.org/browse/JDK-8327247
Fixed in JDK 23
© 2025 NTT DATA Japan Corporation 41
Additional Note: JIT Compilers in HotSpot VM
• C1 and C2
- C1 has a short compilation time but
generates slower machine code.
- C2 has a longer compilation time but
generates faster machine code.
- After a method is used a certain
number of times, it is first JIT-compiled
with C1, and if used even more, it is
JIT-compiled again with C2.
© 2025 NTT DATA Japan Corporation 42
What happens if you run this code on JDK 22?
public static void main(String[] args) {
long start = System.currentTimeMillis();
long sink = 0L;
while (System.currentTimeMillis() - start < 60000) {
sink += new Test().toString().length();
}
System.out.println(sink);
}
To compile toString()
with C2
© 2025 NTT DATA Japan Corporation 43
Run on OpenJDK 22
$ java -XX:CompileCommand=MemStat,Test::toString,print Test
c1 Arena usage Test::toString(()Ljava/lang/String;): 23795992 [na 0 ra 22814112]
(33712->23829704->23829704)
c2 Arena usage Test::toString(()Ljava/lang/String;): 1169778424 [na 136679016 ra 1004706496]
(33712->1169812136->2521320)
Compilation memory statistics
Legend:
total : memory allocated via arenas while compiling
NA : ...how much in node arenas (if c2)
RA : ...how much in resource areas
result : Result: 'ok' finished successfully, 'oom' hit memory limit, 'err' compilation failed
...
total NA RA result #nodes time type #rc thread
1169778424 136679016 1004706496 ok 128797 25.622 c2 2 0x00007ffaf80e20c0
method
Test::toString(()Ljava/lang/String;) This compilation used
1.1GB of memory
(Linux-x64, Intel(R) Xeon(R) Platinum 8260M CPU @ 2.40GHz) OpenJDK 22
© 2025 NTT DATA Japan Corporation 44
Issue in JDK Versions
• JDK 8:
• This problem does not occur in JDK8.
• Example versions: 8u401, 8u275.
• From JDK 9 Onwards:
• This problem has arisen but does not occur with all string
concatenations.
• Occurs in specific cases.
• Specific Cases:
• When using v1 + " " + v2 + " " + ... + " " + vn,
memory and compile time rapidly increase.
• With 3-4 Strings, it goes unnoticed.
• With 50, 100, or 123 Strings, the increase is significant.
© 2025 NTT DATA Japan Corporation 45
Changes in String Concatenation from Java 9
Due to the implementation of indy,
there have been many cases where
the execution performance of
concatenation has improved.
This issue is a rare bug case among
the majority of problem-free instances.
© 2025 NTT DATA Japan Corporation 46
Discussion Topics
• Internal Structure of String Concatenation:
• We want to discuss this, but time doesn't permit today.
• Class File Theme:
• Let's stick to this theme.
• Exploration Topics:
• How it was before indy.
• Why string concatenation was changed.
• What indy is.
© 2025 NTT DATA Japan Corporation 47
Simpler Example
public class Test2 {
private String f0 = "1";
@Override
public String toString() {
return f0 + ",";
}
}
© 2025 NTT DATA Japan Corporation 48
Disassembling with javap
// Java 8
new #4 // class java/lang/StringBuilder
dup
invokespecial #5 // Method java/lang/StringBuilder."<init>":()V
aload_0
getfield #3 // Field f0:Ljava/lang/String;
invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
ldc #7 // String ,
invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
invokevirtual #8 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
$ javap -c Test2
© 2025 NTT DATA Japan Corporation 49
Need for Improvement
• String Concatenation:
• Frequently used, no issues with the process itself.
• Need to improve execution performance.
• Using StringBuilder:
• Requires changes to the class file output.
• Java compiler needs modification.
• Solution:
• Devised a method to change only the JVM.
• No need to alter class files or the compiler.
© 2025 NTT DATA Japan Corporation 50
Introduction of Indy
• Purpose of Indy:
• Provides a mechanism where the method to be called is determined at
runtime.
• Initially introduced in Java 7 .
• Improves performance for dynamically-typed languages
such as JRuby.
• Bootstrap Method:
• The method executed before the first invocation of an indy instruction.
© 2025 NTT DATA Japan Corporation 51
Bootstrap Method
invokedynamic #15, 0
Bootstrap method is called
Bootstrap method
Retrieve the method corresponding
to this indy
CallSite
MethodHandle
Execute the
corresponding method
Only the first time
From the second time onwards
© 2025 NTT DATA Japan Corporation 52
Indify String Concatenation
// Java 8
new #4 // class java/lang/StringBuilder
dup
invokespecial #5 // Method java/lang/StringBuilder."<init>":()V
aload_0
getfield #3 // Field f0:Ljava/lang/String;
invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
ldc #7 // String ,
invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
invokevirtual #8 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
$ javap -c Test2
// Java 9
aload_0
getfield #9 // Field f0:Ljava/lang/String;
invokedynamic #15, 0 // InvokeDynamic #0:makeConcatWithConstants:(Ljava/lang/String;)Ljava/lang/String;
areturn
© 2025 NTT DATA Japan Corporation 53
String Concatenation with Indy
• Class File Content:
• The class file only includes the invokedynamic instruction.
• Concatenation Process:
• The specifics of the concatenation process are shifted to the bootstrap
method.
• Implementation Modification:
• Only the related implementation needs modification without changing
the class file.
© 2025 NTT DATA Japan Corporation 54
String Concatenation with Indy
...
aload_0
getfield #9 // Field f0:Ljava/lang/String;
invokedynamic #15, 0 // InvokeDynamic #0:makeConcatWithConstants:(Ljava/lang/String;)Ljava/lang/String;
areturn
}
BootstrapMethods:
0: #28 invokestatic java/lang/invoke/StringConcatFactory.makeConcatWithConstants:
(Ljava/lang/invoke/MethodHandles$Lookup;
Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;
[Ljava/lang/Object;
)Ljava/lang/invoke/CallSite;
Method arguments:
#26 ,
private String f0 = "1";
public String toString() {
return f0 + ",";
}
© 2025 NTT DATA Japan Corporation 55
Handling Bugs in String Concatenation
• Adjust StringConcatFactory class.
© 2025 NTT DATA Japan Corporation 56
Handling Bugs in String Concatenation
• Adjust StringConcatFactory class.
© 2025 NTT DATA Japan Corporation 57
Resolution in Java 23
$ java -XX:CompileCommand=MemStat,Test::toString,print Test
...
Compilation memory statistics
Legend:
total : memory allocated via arenas while compiling
...
(The following is an excerpt)
total NA RA result #nodes limit time type method
6419424 2456608 1374856 err 2621 1024M 0.390 c2 Test::toString(()Ljava/lang/S
1243664 0 1112752 ok - 1024M 0.393 c1 Test::toString(()Ljava/lang/S
(Linux-x64, Intel(R) Xeon(R) Platinum 8260M CPU @ 2.40GHz) OpenJDK 22
© 2025 NTT DATA Japan Corporation
© 2025 NTT DATA Japan Corporation 58
Achievements with Indy
5
© 2025 NTT DATA Japan Corporation 59
Quoted : Performance Comparison Before and After
Indifying
https://cl4es.github.io/presentations/jvmls2025/draft.html
Further improvements
have been made in each
version since JDK 10.
(Linux-x64, Intel(R) Xeon(R) Platinum 8358 CPU @ 2.60GHz)
© 2025 NTT DATA Japan Corporation 60
Benefits and Drawbacks of Indy
Advantages Drawbacks
• Improvements can be made
without changing the class
file output.
• Simply upgrading the version
without recompiling applies
these improvements.
• Using indy makes JIT
compilation more efficient
compared to StringBuilder.
• Slight overhead introduced
by using bootstrap methods.
(30〜90ms in JDK 9[1])
• Subsequent bootstraps
execute only part of the
aforementioned overhead.
[1] https://cl4es.github.io/2019/05/14/String-Concat-Redux.html
• From Java 9 to 13, efforts have been
made to reduce this overhead.
• Currently, the implementation is slightly
heavier than Java 8.
© 2025 NTT DATA Japan Corporation 61
Additional Resources on Indy Improvements
• Details Beyond Today's Scope:
• Unfortunately, discussing the details of these improvements is beyond
the scope of today's session.
• Related Sessions:
• There were sessions about this topic at the JVM Language Summit
- Re-thinking Java String Concatenation
- https://youtu.be/tgX38gvMpjs?si=lwVLxi2jElYIRgyZ
© 2025 NTT DATA Japan Corporation 62
Advantages of Upgrading Java Versions
• Performance Improvement:
• Upgrading Java versions improves overall execution performance
without changing the code.
• Enhanced Tools:
• Keeping Java versions updated not only enhances performance but also
improves the tools provided with the JDK.
© 2025 NTT DATA Japan Corporation
© 2025 NTT DATA Japan Corporation 63
Wrap Up
6
© 2025 NTT DATA Japan Corporation 64
Summary of Today's Session
• Synthetic Methods with Covariant Returns:
• Covered in detail.
• Class File Differences:
• Before and after Java 11 with nestmates.
• String Concatenation Improvements with Indy:
• Discussed the enhancements.
© 2025 NTT DATA Japan Corporation 65
Encouragement for Further Exploration
• Beyond Coding:
• Today, I wanted to share the joy of exploring how Java works rather
than just focusing on how to write code or use new features.
• Explore Further:
• I hope you'll try out what we've discussed and explore further after this
session.
Unveiling the Hidden Layers of Java Class Files: Beyond Bytecode (Devnexus 2025)