Projects Panama, Valhalla, and Babylon: Java is the New Python v0.9

yanngaelgueheneuc 384 views 172 slides Mar 06, 2025
Slide 1
Slide 1 of 172
Slide 1
1
Slide 2
2
Slide 3
3
Slide 4
4
Slide 5
5
Slide 6
6
Slide 7
7
Slide 8
8
Slide 9
9
Slide 10
10
Slide 11
11
Slide 12
12
Slide 13
13
Slide 14
14
Slide 15
15
Slide 16
16
Slide 17
17
Slide 18
18
Slide 19
19
Slide 20
20
Slide 21
21
Slide 22
22
Slide 23
23
Slide 24
24
Slide 25
25
Slide 26
26
Slide 27
27
Slide 28
28
Slide 29
29
Slide 30
30
Slide 31
31
Slide 32
32
Slide 33
33
Slide 34
34
Slide 35
35
Slide 36
36
Slide 37
37
Slide 38
38
Slide 39
39
Slide 40
40
Slide 41
41
Slide 42
42
Slide 43
43
Slide 44
44
Slide 45
45
Slide 46
46
Slide 47
47
Slide 48
48
Slide 49
49
Slide 50
50
Slide 51
51
Slide 52
52
Slide 53
53
Slide 54
54
Slide 55
55
Slide 56
56
Slide 57
57
Slide 58
58
Slide 59
59
Slide 60
60
Slide 61
61
Slide 62
62
Slide 63
63
Slide 64
64
Slide 65
65
Slide 66
66
Slide 67
67
Slide 68
68
Slide 69
69
Slide 70
70
Slide 71
71
Slide 72
72
Slide 73
73
Slide 74
74
Slide 75
75
Slide 76
76
Slide 77
77
Slide 78
78
Slide 79
79
Slide 80
80
Slide 81
81
Slide 82
82
Slide 83
83
Slide 84
84
Slide 85
85
Slide 86
86
Slide 87
87
Slide 88
88
Slide 89
89
Slide 90
90
Slide 91
91
Slide 92
92
Slide 93
93
Slide 94
94
Slide 95
95
Slide 96
96
Slide 97
97
Slide 98
98
Slide 99
99
Slide 100
100
Slide 101
101
Slide 102
102
Slide 103
103
Slide 104
104
Slide 105
105
Slide 106
106
Slide 107
107
Slide 108
108
Slide 109
109
Slide 110
110
Slide 111
111
Slide 112
112
Slide 113
113
Slide 114
114
Slide 115
115
Slide 116
116
Slide 117
117
Slide 118
118
Slide 119
119
Slide 120
120
Slide 121
121
Slide 122
122
Slide 123
123
Slide 124
124
Slide 125
125
Slide 126
126
Slide 127
127
Slide 128
128
Slide 129
129
Slide 130
130
Slide 131
131
Slide 132
132
Slide 133
133
Slide 134
134
Slide 135
135
Slide 136
136
Slide 137
137
Slide 138
138
Slide 139
139
Slide 140
140
Slide 141
141
Slide 142
142
Slide 143
143
Slide 144
144
Slide 145
145
Slide 146
146
Slide 147
147
Slide 148
148
Slide 149
149
Slide 150
150
Slide 151
151
Slide 152
152
Slide 153
153
Slide 154
154
Slide 155
155
Slide 156
156
Slide 157
157
Slide 158
158
Slide 159
159
Slide 160
160
Slide 161
161
Slide 162
162
Slide 163
163
Slide 164
164
Slide 165
165
Slide 166
166
Slide 167
167
Slide 168
168
Slide 169
169
Slide 170
170
Slide 171
171
Slide 172
172

About This Presentation

Java has had a tremendous success and, in the last few years, has evolved quite significantly. However, it was still difficult to interface with libraries written in other programming language because of some complexity with JNI and some syntactic and semantic barriers. New projects to improve Java ...


Slide Content

Yann-Gaël Guéhéneuc
(/jan/, he/il)
Work licensed under Creative Commons
BY-NC-SA 4.0 International
Java is the New Python
(Or How to Open the World)
Version 0.9
25/03/05

2/172
Any questions/comments are welcome at
[email protected]
Source code available at
https://github.com/ptidejteam/tutorials -
JavaIsTheNewPython

3/172
Inspiration 
2025 Is the Last Year of Python Dominance
in AI: Java Comin’
–https://thenewstack.io/2025-is-the-last-year-of-
python-dominance-in-ai-java-comin/

The Isthmus in the VM
–https://cr.openjdk.org/~jrose/panama/isthmus-in -
the-vm-2014.html

4/172
Observations 
Machine learning / AI has made some great
progress in recent years

By coincidence, most libraries are written in
C++ or Python

5/172
Observations C++ 
Complexity of the syntax

Complexity of the semantic

Multiple ways to do the
same things 
No garbage collector

No memory safety
Python

Python is slow at runtime

Cannot do mobile apps

Difficult to use with other
languages 
High memory consumption

Not used in enterprise
development 
Runtime errors

Simplicity
https://www.geeksforgeeks.org/advantages-and-disadvantages-of-cpp/
https://www.geeksforgeeks.org/disadvantages-of-python/

6/172
Observations 
“However, enterprises are realizing that Java
is the better choice for enterprise -level
deployments.
We’re likely to see Java
outpace Python within the next 18
months to three years.

—Simon Ritter, deputy CTO,
Azul Systems, January 2025

7/172
Observations 
“However, enterprises are realizing that Java
is the better choice for enterprise -level
deployments.
We’re likely to see Java
outpace Python within the next 18
months to three years.

—Simon Ritter, deputy CTO,
Azul Systems, January 2025
Emphasis mine

8/172
Questions 
In Java
–How to best use existing libraries (C++, Python)?
–How to best use “new” hardware (GPUs)?

9/172
Questions 
In Java
–How to best open JVM’s closed world?
–How to best bridge memory models?

10/172
https://saf-astronomie.fr/listhme-de-penthievre-et-la- cote-sauvage/
Security
Managed memory
Garbage collection
Unmanaged memory
Unsecure
The Isthmus in the JVM

11/172
IN DETAILS

12/172
The Isthmus in the JVM 1.
Syntax: lambdas vs. function pointers, no C macros, no C++ templates
2.
Naming: naming and scoping
3.
Data types: Booleans, strings, which always have he aders
4.
Storage management: many native libraries operate through pointers
to memory, garbage collection
5.
Exceptions: C++ and Java exceptions behave differently; C APIs
sometimes require ad hoc polling for errors
6.
Semantics: Java strings are immutable while C “stri ngs” are character
arrays, C++ strings are yet different
7.
Performance: strings, boxing, copying cause perform ance “potholes”
8.
Safety: the JVM must continue to operate correctly even in the face of
errors or abuse of any single API
https://cr.openjdk.org/~jrose/panama/isthmus-in-the-vm-2 014.html

13/172
1.
Syntax

Java lambdas

C/C++ function pointers
static void
methodNeedingSomeComparator(
final
BiFunction<Integer, Integer, Integer>
aComparator
) {
System.
out
.println(
aComparator
.apply(1, 2));
System.
out
.println(
aComparator
);
}
...
final
BiFunction<Integer, Integer, Integer>
max4
= Math::max;
Main.methodNeedingSomeComparator(
max4
);
System.
out
.println(
max4
);
typedef int
(*
fp_max_comparator
)(
const int
,
const int
);
void
function_needing_some_comparator(
const
fp_max_comparator
comparator)
{
printf
(
"%d\n"
, compartor(1, 2));
}
int
my_max_function(
const int
a,
const int
b) { ... }
...
function_needing_some_comparator(&my_max_function);

14/172
interface
Executable {
int
myMax(
final int
a
,
final int
b
);
}
class
MyExecutable
implements
Executable {
public int
myMax(
final int
a
,
final int
b
) {
return
Math.max(
a
,
b
);
}
}
final
MyExecutable
max1
=
new
MyExecutable();
System.
out
.println(
max1
.myMax(1, 2));
class
MySecondExecutable
implements
BiFunction<Integer, Integer, Integer> {
public
Integer apply(
final
Integer
a
,
final
Integer
b
) {
return
Math.max(
a
,
b
);
}
}
final
MySecondExecutable
max2
=
new
MySecondExecutable();
Syntax.methodNeedingSomeComparator(
max2
);
final
BiFunction<Integer, Integer, Integer>
max3
=
new
BiFunction<Integer, Integer, Integer>() {
public
Integer apply(
final
Integer
a
,
final
Integer
b
) {
return
Math.max(
a
,
b
);
}
};
Syntax.methodNeedingSomeComparator(
max3
);
final
BiFunction<Integer, Integer, Integer>
max4
= (
final
Integer
a
,
final
Integer
b
) ->
{
return
Math.max(
a
,
b
); };
Syntax.methodNeedingSomeComparator(
max4
);
final
BiFunction<Integer, Integer, Integer>
max5
= Math::max;
Syntax.methodNeedingSomeComparator(
max5
);

15/172
interface
Executable {
int
myMax(
final int
a
,
final int
b
);
}
class
MyExecutable
implements
Executable {
public int
myMax(
final int
a
,
final int
b
) {
return
Math.max(
a
,
b
);
}
}
final
MyExecutable
max1
=
new
MyExecutable();
System.
out
.println(
max1
.myMax(1, 2));
class
MySecondExecutable
implements
BiFunction<Integer, Integer, Integer> {
public
Integer apply(
final
Integer
a
,
final
Integer
b
) {
return
Math.max(
a
,
b
);
}
}
final
MySecondExecutable
max2
=
new
MySecondExecutable();
Syntax.methodNeedingSomeComparator(
max2
);
final
BiFunction<Integer, Integer, Integer>
max3
=
new
BiFunction<Integer, Integer, Integer>() {
public
Integer apply(
final
Integer
a
,
final
Integer
b
) {
return
Math.max(
a
,
b
);
}
};
Syntax.methodNeedingSomeComparator(
max3
);
final
BiFunction<Integer, Integer, Integer>
max4
= (
final
Integer
a
,
final
Integer
b
) ->
{
return
Math.max(
a
,
b
); };
Syntax.methodNeedingSomeComparator(
max4
);
final
BiFunction<Integer, Integer, Integer>
max5
= Math::max;
Syntax.methodNeedingSomeComparator(
max5
);
Can’t be used by the method needing it…

16/172
1.
Syntax

Outputs and object types
2
net.ptidej.isthmus.Syntax$1MyExecutable@372f7a8d
2
net.ptidej.isthmus.Syntax$1MySecondExecutable@28a418fc
2
net.ptidej.isthmus.Syntax$1@1f32e575
2
net.ptidej.isthmus.Syntax$$Lambda/0x0000028e58001240@77459877
2
net.ptidej.isthmus.Syntax$$Lambda/0x0000028e58001470@33c7353a

17/172
2.
Naming
Java 
Separation
C++

No separation
public class
Naming {
public int
identifier
= 0;
public int
identifier() {
return
0;
}
}
class
Naming
{
public
:
int
identifier
= 0;
void
identifier() {
}
};
error: 'void Naming::identifier()'
conflicts with a previous declaration

18/172
2.
Naming
Java 
No nesting

Impact on visibility
C++

Nesting

No impact on visibility
package
a.b;
public class
X {
}
package
b;
public class
X {
}
public static void
main(String[]
args
) {
System.
out
.println(a.b.X.
class
);
System.
out
.println(b.X.
class
);
}
namespace
a {
namespace
b {
int
x = 0;
}
}
namespace
b {
string
x;
}
using namespace
a;
void
foo() {
b::x = 42;
}
error: reference to 'b' is ambiguous

19/172
2.
Naming
Java 
Modules
C++

No equivalent
– Maybe linker libs?
module
isthmus.java {
requires
java.logging;
}
package
net.ptidej.isthmus;
import
java.util.logging.Logger;
public class
Main {
private static
Logger
java. Logging
=
Logger.getLogger(
"net.ptidej.isthmus"
);
public static void
main(
final
String[]
args
) {
Main.
logger
.fine(
"Hello, World!"
);
}
}

20/172
3.
Data types
Java 
Booleans are their own

Strings are immutable
C/C++

Booleans are shorts

Strings are mutable
bool
a[5];
bool
result;
for
(
int
i = 0; i < 5; i++) {
cout << a[i] <<
" "
;
result += a[i];
}
cout <<
endl
<< result <<
endl
;
boolean
a
[] =
new boolean
[5];
for
(
int
i
= 0;
i
< 5;
i
++) {
System.
out
.println(
a
[
i
]);
}
string
string1 =
"Hello"
;
string
string2 =
", World!"
;
string
string3 = string1 + string2;
cout << string3 <<
endl
;
string3[0] =
'Y'
;
cout << string3 <<
endl
;
final
String
string1
=
"Hello"
;
final
String
string2
=
", World!"
;
final
String
string3
=
string1
+
string2
;
System.
out
.println(
string3
);
final
StringBuilder
string4
=
new
StringBuilder(
string3
);
string4
.setCharAt(0,
'Y'
);
System.
out
.println(
string4
);

21/172
3.
Data types
Java 
Performance

Generics
– Autoboxing
C/C++

Performance

Consistency
public interface
IntFunction<R>
public interface
ToIntFunction<T>
vs. Predicate<
int
,
int
>
using namespace
std;
void
abssort(
float
*x,
unsigned
n) {
sort(x, x + n, [](
float
a,
float
b) {
return
(abs(a) < abs(b)); });
}

22/172
3.
Data types
Java 
Primitive types

Objects and references
C/C++

Primitive types

Pointers
https://stackoverflow.com/questions/373419/whats-th e-difference-between-
passing-by-reference-vs-passing-by-value

23/172
4.
Storage management
Java 
Objects

Garbage collection
C/C++

Pointers

Memory lifetime
https://www.baeldung.com/java-stack-heap
https://study.com/academy/lesson/program-memory-in-c-programming.html
vs.

24/172
5.
Exceptions
Java 
NullPointerException

Exceptions are objects and
thrown consistently
C/C++

nullvalues
– One of the purpose of Rust! 
Some errors must be
polled actively int
example_errno() { const char
*filename =
"somefile.txt"
;
ifstream
file(filename);
if
(!file) {
switch
(errno) {
case
ENOENT:
cerr <<
"Error: File doesn't exist."
<<
endl
;
break
;
...
default
:
cerr <<
"Error: Cannot open file."
<<
endl
;
break
;
}
return
1;
// Some error happened
}
...

25/172
6.
Semantics

Classes vs. interfaces

Package-only visibility
–Modules
–Sealing

finalvs. const

Single vs. multiple-inheritance
–Virtual vs. non-virtual member functions


https://www.cs.gordon.edu/courses/cs212/paperwork/Java-C++comparison.pdf

26/172
7.
Performance

“Code which uses Java primitives performs
on a par corresponding C code, but…”

https://unriskinsight.blogspot.com/2014/06/fa
st-functional-goats-lions-and-wolves.html
https://www.oracle.com/java/technologies/performance-comparisons.html

27/172
7.
Performance

“Code which uses Java primitives performs
on a par corresponding C code, but…”

https://unriskinsight.blogspot.com/2014/06/fa
st-functional-goats-lions-and-wolves.html
Many threats to validity!
https://www.oracle.com/java/technologies/performance-comparisons.html

28/172
8.
Safety

No attacks from untrusted code

No privilege escalation from untrusted code

No crashes

No leaks

No hangs

Rare outages

No unguarded casts

29/172
8.
Safety

No attacks from untrusted code

No privilege escalation from untrusted code

No crashes

No leaks

No hangs

Rare outages

No unguarded casts
See later…

30/172
ANSWERS

31/172
Three-prong Approach
https://en.wikipedia.org/wiki/Valhalla
https://www.historyextra.com/period/ancient-history/baby lon-babylonia-tower-babel-hanging-gardens-hammurabi/
https://www.georgeglazer.com/wpmain/product/where-atlantic-pacific-meet-the-panama-canal-to-day-birds-eye-v iew-by-richard-rummell-1914/

32/172
Three-prong Approach
https://en.wikipedia.org/wiki/Valhalla
https://www.historyextra.com/period/ancient-history/baby lon-babylonia-tower-babel-hanging-gardens-hammurabi/
https://www.georgeglazer.com/wpmain/product/where-atlantic-pacific-meet-the-panama-canal-to-day-birds-eye-v iew-by-richard-rummell-1914/

33/172
Three-prong Approach
https://en.wikipedia.org/wiki/Valhalla
https://www.historyextra.com/period/ancient-history/baby lon-babylonia-tower-babel-hanging-gardens-hammurabi/
https://www.georgeglazer.com/wpmain/product/where-atlantic-pacific-meet-the-panama-canal-to-day-birds-eye-v iew-by-richard-rummell-1914/

34/172
Three-prong Approach
https://en.wikipedia.org/wiki/Valhalla
https://www.historyextra.com/period/ancient-history/baby lon-babylonia-tower-babel-hanging-gardens-hammurabi/
https://www.georgeglazer.com/wpmain/product/where-atlantic-pacific-meet-the-panama-canal-to-day-birds-eye-v iew-by-richard-rummell-1914/

35/172
Three-prong Approach 
Project PanamaFFI

Project Valhallavalue class/objects

Project Babyloncode reflection

36/172
Project Panama

37/172
Foreign Function Interface 
Early access build from Project Valhalla
–https://jdk.java.net/jextract/
–JDK 22 + JExtract v6.47 (24/10/09)

38/172
Java Native Interface 
Write Java code with native methods
–And System.loadLibrary()

Generate header file with javah
–javac -hsince Java 10

Implement the header file

Compile the Java code
–Can be done earlier too

Run the compile code

39/172
Java Native Interface
package
net.ptidej.panama.jni;
public class
Main {
static
{
System.loadLibrary(
"net_ptidej_panama_jni_Main"
);
}
public static native int
stringLength(
final
String
s
);
public static void
main(
final
String[]
args
) {
final
String
s
=
"Hello, world!"
;
System.
out
.println(Main.stringLength(
s
));
}
}
/* DO NOT EDIT THIS FILE - it is machine generated */ #include
<jni.h>
/* Header for class net_ptidej_panama_jni_Main */ #ifndef
_Included_net_ptidej_panama_jni_Main
#define
_Included_net_ptidej_panama_jni_Main
#ifdef
__cplusplus
extern
"C"
{
#endif /*
* Class: net_ptidej_panama_jni_Main
* Method: stringLength
* Signature: (Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL
Java_net_ptidej_panama_jni_Main_stringLength
(JNIEnv *, jclass, jstring);
#ifdef
__cplusplus
}
#endif
#endif
#include
<cstring>
#include
"net_ptidej_panama_jni_Main.h"
JNIEXPORT jint JNICALL
Java_net_ptidej_panama_jni_Main_stringLength
(JNIEnv *env, jclass jc, jstring js) {
const char
* s = env->GetStringUTFChars(js, NULL);
return
strlen(s);
}

40/172
Java Native Interface
package
net.ptidej.panama.jni;
public class
Main {
static
{
System.loadLibrary(
"net_ptidej_panama_jni_Main"
);
}
public static native int
stringLength(
final
String
s
);
public static void
main(
final
String[]
args
) {
final
String
s
=
"Hello, world!"
;
System.
out
.println(Main.stringLength(
s
));
}
}
/* DO NOT EDIT THIS FILE - it is machine generated */ #include
<jni.h>
/* Header for class net_ptidej_panama_jni_Main */ #ifndef
_Included_net_ptidej_panama_jni_Main
#define
_Included_net_ptidej_panama_jni_Main
#ifdef
__cplusplus
extern
"C"
{
#endif /*
* Class: net_ptidej_panama_jni_Main
* Method: stringLength
* Signature: (Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL
Java_net_ptidej_panama_jni_Main_stringLength
(JNIEnv *, jclass, jstring);
#ifdef
__cplusplus
}
#endif
#endif
#include
<cstring>
#include
"net_ptidej_panama_jni_Main.h"
JNIEXPORT jint JNICALL
Java_net_ptidej_panama_jni_Main_stringLength
(JNIEnv *env, jclass jc, jstring js) {
const char
* s = env->GetStringUTFChars(js, NULL);
return
strlen(s);
}
Opens a door in the JVM

41/172
Java Native Interface
package
net.ptidej.panama.jni;
public class
Main {
static
{
System.loadLibrary(
"net_ptidej_panama_jni_Main"
);
}
public static native int
stringLength(
final
String
s
);
public static void
main(
final
String[]
args
) {
final
String
s
=
"Hello, world!"
;
System.
out
.println(Main.stringLength(
s
));
}
}
/* DO NOT EDIT THIS FILE - it is machine generated */ #include
<jni.h>
/* Header for class net_ptidej_panama_jni_Main */ #ifndef
_Included_net_ptidej_panama_jni_Main
#define
_Included_net_ptidej_panama_jni_Main
#ifdef
__cplusplus
extern
"C"
{
#endif /*
* Class: net_ptidej_panama_jni_Main
* Method: stringLength
* Signature: (Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL
Java_net_ptidej_panama_jni_Main_stringLength
(JNIEnv *, jclass, jstring);
#ifdef
__cplusplus
}
#endif
#endif
#include
<cstring>
#include
"net_ptidej_panama_jni_Main.h"
JNIEXPORT jint JNICALL
Java_net_ptidej_panama_jni_Main_stringLength
(JNIEnv *env, jclass jc, jstring js) {
const char
* s = env->GetStringUTFChars(js, NULL);
return
strlen(s);
}
Opens a door in the JVM
JVM jargon

42/172
Java Native Interface
package
net.ptidej.panama.jni;
public class
Main {
static
{
System.loadLibrary(
"net_ptidej_panama_jni_Main"
);
}
public static native int
stringLength(
final
String
s
);
public static void
main(
final
String[]
args
) {
final
String
s
=
"Hello, world!"
;
System.
out
.println(Main.stringLength(
s
));
}
}
/* DO NOT EDIT THIS FILE - it is machine generated */ #include
<jni.h>
/* Header for class net_ptidej_panama_jni_Main */ #ifndef
_Included_net_ptidej_panama_jni_Main
#define
_Included_net_ptidej_panama_jni_Main
#ifdef
__cplusplus
extern
"C"
{
#endif /*
* Class: net_ptidej_panama_jni_Main
* Method: stringLength
* Signature: (Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL
Java_net_ptidej_panama_jni_Main_stringLength
(JNIEnv *, jclass, jstring);
#ifdef
__cplusplus
}
#endif
#endif
#include
<cstring>
#include
"net_ptidej_panama_jni_Main.h"
JNIEXPORT jint JNICALL
Java_net_ptidej_panama_jni_Main_stringLength
(JNIEnv *env, jclass jc, jstring js) {
const char
* s = env->GetStringUTFChars(js, NULL);
return
strlen(s);
}
Opens a door in the JVM
JVM jargon
JVM C API

43/172
Java Native Interface 
gcc -Wl,--add-stdcall-alias
-shared -I"${JAVA_HOME}"/include
-I"${JAVA_HOME}"/include/win32
-o net_ptidej_panama_jni_Main.dll
net_ptidej_panama_jni_Main.cpp

java net.ptidej.panama.jni.Main
–Prints 13

44/172
Java Native Interface 
Possible bug in the JVM
– “JVM Segmentation Fault with Single-file Source-code
Program and JNI”
• java Main.classwill throw (correctly)
java.lang.UnsatisfiedLinkError
• java Main.javawill also throw (correctly)
java.lang.UnsatisfiedLinkError
• But delete Main.classand java Main.javaeither throws
(correctly) java.lang.UnsatisfiedLinkErrororwrites
Segmentation faultwithout further info. orfreezes and
must be killed
https://easydrawingguides.com/how-to-draw-a-ladybug-really-easy-drawing-tutorial/

45/172
Java Native Interface 
Limitations
–Sits between the two “worlds”
• Some code in Java, some code in C/C++
–Needs marshalling/mapping of data types
–Requires careful idioms
–Could crash the JVM
• Cf. possible Segmentation fault
–Lots of boiler-plate code

46/172
java.lang.foreign.Linker 
Focus on memory

Increase amount of Java code

Remove all C boiler-plate code

47/172
java.lang.foreign.Linker
public class
Main {
public static void
main(
final
String[]
args
)
throws
Throwable {
final
Linker
linker
= Linker.nativeLinker();
final
SymbolLookup
dll
= SymbolLookup.libraryLookup(
"net_ptidej_panama_version2_Main.dll"
, Arena.global());
final
MethodHandle
strlen
=
linker
.downcallHandle(
dll
.find(
"stringLength"
).orElseThrow(),
FunctionDescriptor.of(
ValueLayout.
JAVA_LONG
, ValueLayout.
ADDRESS
));
try
(
final
Arena
arena
= Arena.ofConfined()) {
final
MemorySegment
cString
=
arena
.allocateFrom(
"Hello, World!"
);
final long
length
= (
long
)
strlen
.invoke(
cString
);
System.
out
.println(
length
);
}
}
}
#include
<cstring>
#include
"net_ptidej_panama_version2_Main.h"
long
stringLength(
const char
*s) {
return
strlen(s);
}

48/172
java.lang.foreign.Linker
public class
Main {
public static void
main(
final
String[]
args
)
throws
Throwable {
final
Linker
linker
= Linker.nativeLinker();
final
SymbolLookup
dll
= SymbolLookup.libraryLookup(
"net_ptidej_panama_version2_Main.dll"
, Arena.global());
final
MethodHandle
strlen
=
linker
.downcallHandle(
dll
.find(
"stringLength"
).orElseThrow(),
FunctionDescriptor.of(
ValueLayout.
JAVA_LONG
, ValueLayout.
ADDRESS
));
try
(
final
Arena
arena
= Arena.ofConfined()) {
final
MemorySegment
cString
=
arena
.allocateFrom(
"Hello, World!"
);
final long
length
= (
long
)
strlen
.invoke(
cString
);
System.
out
.println(
length
);
}
}
}
#include
<cstring>
#include
"net_ptidej_panama_version2_Main.h"
long
stringLength(
const char
*s) {
return
strlen(s);
}
Much simpler and
“natural” C code

49/172
java.lang.foreign.Linker 
Linker
– nativeLinker() 
SymbolLookup
– libraryLookup() 
MethodHandle
– invoke() 
Arena
– global()
– ofConfined()

MemorySegment
– allocateFrom()

ABI (Application Binary Interface)
– Linker for the ABI of the native platform 
A symbol is a named entity
– Loads a library, creates a lookup 
A typed, executable entity
– Invokes the method handle 
Controls the life of native memory
– Program-long, thread-friendly, zeroed
– Temporary, zeroed

A contiguous region of memory
– New memory segment initialised with
the provided, converted value

50/172
java.lang.foreign.Linker 
Advantages
–Simpler, natural C code
–More Java code

Limitations
–Must handle manually the foreign library

51/172
java.lang.foreign.Linker
public class
Main {
public static void
main(
final
String[]
args
)
throws
Throwable {
final
Linker
linker
= Linker.nativeLinker();
final
SymbolLookup
stringh
=
linker
.defaultLookup();
final
MethodHandle
strlen
=
linker
.downcallHandle(
stringh
.find(
"strlen"
).orElseThrow(),
FunctionDescriptor.of(ValueLayout.
JAVA_LONG
,
ValueLayout.
ADDRESS
));
try
(
final
Arena
arena
= Arena.ofConfined()) {
final
MemorySegment
cString
=
arena
.allocateFrom(
"Hello, World!"
);
final long
length
= (
long
)
strlen
.invokeExact(
cString
);
System.
out
.println(
length
);
}
}
}

52/172
java.lang.foreign.Linker
public class
Main {
public static void
main(
final
String[]
args
)
throws
Throwable {
final
Linker
linker
= Linker.nativeLinker();
final
SymbolLookup
stringh
=
linker
.defaultLookup();
final
MethodHandle
strlen
=
linker
.downcallHandle(
stringh
.find(
"strlen"
).orElseThrow(),
FunctionDescriptor.of(ValueLayout.
JAVA_LONG
,
ValueLayout.
ADDRESS
));
try
(
final
Arena
arena
= Arena.ofConfined()) {
final
MemorySegment
cString
=
arena
.allocateFrom(
"Hello, World!"
);
final long
length
= (
long
)
strlen
.invokeExact(
cString
);
System.
out
.println(
length
);
}
}
}
Default lookup

53/172
java.lang.foreign.Linker
public class
Main {
public static void
main(
final
String[]
args
)
throws
Throwable {
final
Linker
linker
= Linker.nativeLinker();
final
SymbolLookup
stringh
=
linker
.defaultLookup();
final
MethodHandle
strlen
=
linker
.downcallHandle(
stringh
.find(
"strlen"
).orElseThrow(),
FunctionDescriptor.of(ValueLayout.
JAVA_LONG
,
ValueLayout.
ADDRESS
));
try
(
final
Arena
arena
= Arena.ofConfined()) {
final
MemorySegment
cString
=
arena
.allocateFrom(
"Hello, World!"
);
final long
length
= (
long
)
strlen
.invokeExact(
cString
);
System.
out
.println(
length
);
}
}
}
Default lookup
For a known C function

54/172
java.lang.foreign.Linker 
Advantages
–Simpler, natural C code
–Less Java code

Limitations
–Boiler-plate Java code

55/172
Project Valhalla

56/172
Value Classes and Objects 
Early access build from Project Valhalla
–https://jdk.java.net/valhalla/
–(Partial) JDK 23 + Valhalla

57/172
Java Split Personalities 

58/172
Java Split Personalities 
Everything is an Object

59/172
Java Split Personalities 
Everything is an Object

Except for primitive types
–Eight of them:
boolean
,
byte
,
char
,
short
,
int
,
long
,
float
,
double

60/172
Java Split Personalities 
Everything is an Object

Except for primitive types
–Eight of them:
boolean
,
byte
,
char
,
short
,
int
,
long
,
float
,
double

Except for arrays
–Class of
Object[]
is
[Ljava.lang.Object;

61/172
Java Split Personalities 
Everything is an Object

Except for primitive types
–Eight of them:
boolean
,
byte
,
char
,
short
,
int
,
long
,
float
,
double

Except for arrays
–Class of
Object[]
is
[Ljava.lang.Object;

62/172
Performance Costs 
These exceptions were a good idea
–In 1995
• Memory fetch ≈ Computation like addition

But circumstances have changed
–In 2025
• Cache miss ≈ 1,000 ×computation like addition
• Significant different relative cost

63/172

Heap allocation
–Memory indirections
–Need flat (cache-efficient) and dense
(memory-efficient) data representation

By-reference parameters
–Pointer dereferencing
–Need flat(ter) calling convention to pass
components by values
Performance Costs

64/172
Development Costs 
Generics
–Simpler, consistent APIs
–Primitive types wrinkles

Autoboxing
–Loose identity, gain randomidentity
–Irregularity and cost
–Gotchas
public interface
IntFunction<R>
public interface
ToIntFunction<T>
vs. Predicate<
int
,
int
>

65/172
(Gotchas) try
{final
Integer
a
=
null
;
System.
out
.println(
"a = "
+
a
);
final int
b
=
a
;
System.
out
.println(
"b = "
+
b
);
}
catch
(
final
NullPointerException
e
) {
}
{
final
ResultSet
rs
=
this
.doSomeDatabaseQuery();
final
Double
value
=
rs
.getDouble(
"someDoubleField"
);
}
{
final
Integer
i
=
new
Integer(1);
final
Double
d
=
new
Double(2.0);
System.
out
.println(
"i = "
+
i
);
System.
out
.println(
"d = "
+
d
);
final
Object
o1
=
i
;
System.
out
.println(
"o1 = "
+
o1
);
final
Object
o2
=
true
?
i
:
d
;
System.
out
.println(
"o2 = "
+
o2
);
System.
out
.println(
o1
.equals(
o2
));
}
{
final int
smallNumberInt
= 42;
if
(
smallNumberInt
== 42)
System.
out
.println(
"1."
);
final
Integer
smallNumberInteger
= Integer.valueOf(
42
);
if
(
smallNumberInteger
== (Object) 42)
System.
out
.println(
"2."
);
final int
largeNumberInt
= 500;
if
(
largeNumberInt
== 500)
System.
out
.println(
"3."
);
final
Integer
largeNumberInteger
= Integer.valueOf(
500
);
if
(
largeNumberInteger
== (Object) 500)
System.
out
.println(
"4."
);
}
{
final int
value
= 42;
final
Vector
v
=
new
Vector();
v
.add(
value
);
System.
out
.println(
"first = "
+
v
.getFirst().getClass());
Main.f(
value
,
false
);
}
private static void
f(
final
Object
a
,
final boolean
b
) {
System.
out
.println(
"f(Object a, boolean b)"
);
}
private static void
f(
final
Object
a
,
final
Object
b
) {
System.
out
.println(
"f(Object a, Object b)"
);
}

66/172
(Gotchas) try
{final
Integer
a
=
null
;
System.
out
.println(
"a = "
+
a
);
final int
b
=
a
;
System.
out
.println(
"b = "
+
b
);
}
catch
(
final
NullPointerException
e
) {
}
{
final
ResultSet
rs
=
this
.doSomeDatabaseQuery();
final
Double
value
=
rs
.getDouble(
"someDoubleField"
);
}
{
final
Integer
i
=
new
Integer(1);
final
Double
d
=
new
Double(2.0);
System.
out
.println(
"i = "
+
i
);
System.
out
.println(
"d = "
+
d
);
final
Object
o1
=
i
;
System.
out
.println(
"o1 = "
+
o1
);
final
Object
o2
=
true
?
i
:
d
;
System.
out
.println(
"o2 = "
+
o2
);
System.
out
.println(
o1
.equals(
o2
));
}
{
final int
smallNumberInt
= 42;
if
(
smallNumberInt
== 42)
System.
out
.println(
"1."
);
final
Integer
smallNumberInteger
= Integer.valueOf(
42
);
if
(
smallNumberInteger
== (Object) 42)
System.
out
.println(
"2."
);
final int
largeNumberInt
= 500;
if
(
largeNumberInt
== 500)
System.
out
.println(
"3."
);
final
Integer
largeNumberInteger
= Integer.valueOf(
500
);
if
(
largeNumberInteger
== (Object) 500)
System.
out
.println(
"4."
);
}
{
final int
value
= 42;
final
Vector
v
=
new
Vector();
v
.add(
value
);
System.
out
.println(
"first = "
+
v
.getFirst().getClass());
Main.f(
value
,
false
);
}
private static void
f(
final
Object
a
,
final boolean
b
) {
System.
out
.println(
"f(Object a, boolean b)"
);
}
private static void
f(
final
Object
a
,
final
Object
b
) {
System.
out
.println(
"f(Object a, Object b)"
);
}
NullPointerException

67/172
(Gotchas) try
{final
Integer
a
=
null
;
System.
out
.println(
"a = "
+
a
);
final int
b
=
a
;
System.
out
.println(
"b = "
+
b
);
}
catch
(
final
NullPointerException
e
) {
}
{
final
ResultSet
rs
=
this
.doSomeDatabaseQuery();
final
Double
value
=
rs
.getDouble(
"someDoubleField"
);
}
{
final
Integer
i
=
new
Integer(1);
final
Double
d
=
new
Double(2.0);
System.
out
.println(
"i = "
+
i
);
System.
out
.println(
"d = "
+
d
);
final
Object
o1
=
i
;
System.
out
.println(
"o1 = "
+
o1
);
final
Object
o2
=
true
?
i
:
d
;
System.
out
.println(
"o2 = "
+
o2
);
System.
out
.println(
o1
.equals(
o2
));
}
{
final int
smallNumberInt
= 42;
if
(
smallNumberInt
== 42)
System.
out
.println(
"1."
);
final
Integer
smallNumberInteger
= Integer.valueOf(
42
);
if
(
smallNumberInteger
== (Object) 42)
System.
out
.println(
"2."
);
final int
largeNumberInt
= 500;
if
(
largeNumberInt
== 500)
System.
out
.println(
"3."
);
final
Integer
largeNumberInteger
= Integer.valueOf(
500
);
if
(
largeNumberInteger
== (Object) 500)
System.
out
.println(
"4."
);
}
{
final int
value
= 42;
final
Vector
v
=
new
Vector();
v
.add(
value
);
System.
out
.println(
"first = "
+
v
.getFirst().getClass());
Main.f(
value
,
false
);
}
private static void
f(
final
Object
a
,
final boolean
b
) {
System.
out
.println(
"f(Object a, boolean b)"
);
}
private static void
f(
final
Object
a
,
final
Object
b
) {
System.
out
.println(
"f(Object a, Object b)"
);
}

68/172
(Gotchas) try
{final
Integer
a
=
null
;
System.
out
.println(
"a = "
+
a
);
final int
b
=
a
;
System.
out
.println(
"b = "
+
b
);
}
catch
(
final
NullPointerException
e
) {
}
{
final
ResultSet
rs
=
this
.doSomeDatabaseQuery();
final
Double
value
=
rs
.getDouble(
"someDoubleField"
);
}
{
final
Integer
i
=
new
Integer(1);
final
Double
d
=
new
Double(2.0);
System.
out
.println(
"i = "
+
i
);
System.
out
.println(
"d = "
+
d
);
final
Object
o1
=
i
;
System.
out
.println(
"o1 = "
+
o1
);
final
Object
o2
=
true
?
i
:
d
;
System.
out
.println(
"o2 = "
+
o2
);
System.
out
.println(
o1
.equals(
o2
));
}
{
final int
smallNumberInt
= 42;
if
(
smallNumberInt
== 42)
System.
out
.println(
"1."
);
final
Integer
smallNumberInteger
= Integer.valueOf(
42
);
if
(
smallNumberInteger
== (Object) 42)
System.
out
.println(
"2."
);
final int
largeNumberInt
= 500;
if
(
largeNumberInt
== 500)
System.
out
.println(
"3."
);
final
Integer
largeNumberInteger
= Integer.valueOf(
500
);
if
(
largeNumberInteger
== (Object) 500)
System.
out
.println(
"4."
);
}
{
final int
value
= 42;
final
Vector
v
=
new
Vector();
v
.add(
value
);
System.
out
.println(
"first = "
+
v
.getFirst().getClass());
Main.f(
value
,
false
);
}
private static void
f(
final
Object
a
,
final boolean
b
) {
System.
out
.println(
"f(Object a, boolean b)"
);
}
private static void
f(
final
Object
a
,
final
Object
b
) {
System.
out
.println(
"f(Object a, Object b)"
);
}
Never null (even if missing)

69/172
(Gotchas) try
{final
Integer
a
=
null
;
System.
out
.println(
"a = "
+
a
);
final int
b
=
a
;
System.
out
.println(
"b = "
+
b
);
}
catch
(
final
NullPointerException
e
) {
}
{
final
ResultSet
rs
=
this
.doSomeDatabaseQuery();
final
Double
value
=
rs
.getDouble(
"someDoubleField"
);
}
{
final
Integer
i
=
new
Integer(1);
final
Double
d
=
new
Double(2.0);
System.
out
.println(
"i = "
+
i
);
System.
out
.println(
"d = "
+
d
);
final
Object
o1
=
i
;
System.
out
.println(
"o1 = "
+
o1
);
final
Object
o2
=
true
?
i
:
d
;
System.
out
.println(
"o2 = "
+
o2
);
System.
out
.println(
o1
.equals(
o2
));
}
{
final int
smallNumberInt
= 42;
if
(
smallNumberInt
== 42)
System.
out
.println(
"1."
);
final
Integer
smallNumberInteger
= Integer.valueOf(
42
);
if
(
smallNumberInteger
== (Object) 42)
System.
out
.println(
"2."
);
final int
largeNumberInt
= 500;
if
(
largeNumberInt
== 500)
System.
out
.println(
"3."
);
final
Integer
largeNumberInteger
= Integer.valueOf(
500
);
if
(
largeNumberInteger
== (Object) 500)
System.
out
.println(
"4."
);
}
{
final int
value
= 42;
final
Vector
v
=
new
Vector();
v
.add(
value
);
System.
out
.println(
"first = "
+
v
.getFirst().getClass());
Main.f(
value
,
false
);
}
private static void
f(
final
Object
a
,
final boolean
b
) {
System.
out
.println(
"f(Object a, boolean b)"
);
}
private static void
f(
final
Object
a
,
final
Object
b
) {
System.
out
.println(
"f(Object a, Object b)"
);
}

70/172
(Gotchas) try
{final
Integer
a
=
null
;
System.
out
.println(
"a = "
+
a
);
final int
b
=
a
;
System.
out
.println(
"b = "
+
b
);
}
catch
(
final
NullPointerException
e
) {
}
{
final
ResultSet
rs
=
this
.doSomeDatabaseQuery();
final
Double
value
=
rs
.getDouble(
"someDoubleField"
);
}
{
final
Integer
i
=
new
Integer(1);
final
Double
d
=
new
Double(2.0);
System.
out
.println(
"i = "
+
i
);
System.
out
.println(
"d = "
+
d
);
final
Object
o1
=
i
;
System.
out
.println(
"o1 = "
+
o1
);
final
Object
o2
=
true
?
i
:
d
;
System.
out
.println(
"o2 = "
+
o2
);
System.
out
.println(
o1
.equals(
o2
));
}
{
final int
smallNumberInt
= 42;
if
(
smallNumberInt
== 42)
System.
out
.println(
"1."
);
final
Integer
smallNumberInteger
= Integer.valueOf(
42
);
if
(
smallNumberInteger
== (Object) 42)
System.
out
.println(
"2."
);
final int
largeNumberInt
= 500;
if
(
largeNumberInt
== 500)
System.
out
.println(
"3."
);
final
Integer
largeNumberInteger
= Integer.valueOf(
500
);
if
(
largeNumberInteger
== (Object) 500)
System.
out
.println(
"4."
);
}
{
final int
value
= 42;
final
Vector
v
=
new
Vector();
v
.add(
value
);
System.
out
.println(
"first = "
+
v
.getFirst().getClass());
Main.f(
value
,
false
);
}
private static void
f(
final
Object
a
,
final boolean
b
) {
System.
out
.println(
"f(Object a, boolean b)"
);
}
private static void
f(
final
Object
a
,
final
Object
b
) {
System.
out
.println(
"f(Object a, Object b)"
);
}
Prints
i = 1
d = 2.0
o1 = 1
o2 = 1.0
false

71/172
(Gotchas) try
{final
Integer
a
=
null
;
System.
out
.println(
"a = "
+
a
);
final int
b
=
a
;
System.
out
.println(
"b = "
+
b
);
}
catch
(
final
NullPointerException
e
) {
}
{
final
ResultSet
rs
=
this
.doSomeDatabaseQuery();
final
Double
value
=
rs
.getDouble(
"someDoubleField"
);
}
{
final
Integer
i
=
new
Integer(1);
final
Double
d
=
new
Double(2.0);
System.
out
.println(
"i = "
+
i
);
System.
out
.println(
"d = "
+
d
);
final
Object
o1
=
i
;
System.
out
.println(
"o1 = "
+
o1
);
final
Object
o2
=
true
?
i
:
d
;
System.
out
.println(
"o2 = "
+
o2
);
System.
out
.println(
o1
.equals(
o2
));
}
{
final int
smallNumberInt
= 42;
if
(
smallNumberInt
== 42)
System.
out
.println(
"1."
);
final
Integer
smallNumberInteger
= Integer.valueOf(
42
);
if
(
smallNumberInteger
== (Object) 42)
System.
out
.println(
"2."
);
final int
largeNumberInt
= 500;
if
(
largeNumberInt
== 500)
System.
out
.println(
"3."
);
final
Integer
largeNumberInteger
= Integer.valueOf(
500
);
if
(
largeNumberInteger
== (Object) 500)
System.
out
.println(
"4."
);
}
{
final int
value
= 42;
final
Vector
v
=
new
Vector();
v
.add(
value
);
System.
out
.println(
"first = "
+
v
.getFirst().getClass());
Main.f(
value
,
false
);
}
private static void
f(
final
Object
a
,
final boolean
b
) {
System.
out
.println(
"f(Object a, boolean b)"
);
}
private static void
f(
final
Object
a
,
final
Object
b
) {
System.
out
.println(
"f(Object a, Object b)"
);
}

72/172
(Gotchas) try
{final
Integer
a
=
null
;
System.
out
.println(
"a = "
+
a
);
final int
b
=
a
;
System.
out
.println(
"b = "
+
b
);
}
catch
(
final
NullPointerException
e
) {
}
{
final
ResultSet
rs
=
this
.doSomeDatabaseQuery();
final
Double
value
=
rs
.getDouble(
"someDoubleField"
);
}
{
final
Integer
i
=
new
Integer(1);
final
Double
d
=
new
Double(2.0);
System.
out
.println(
"i = "
+
i
);
System.
out
.println(
"d = "
+
d
);
final
Object
o1
=
i
;
System.
out
.println(
"o1 = "
+
o1
);
final
Object
o2
=
true
?
i
:
d
;
System.
out
.println(
"o2 = "
+
o2
);
System.
out
.println(
o1
.equals(
o2
));
}
{
final int
smallNumberInt
= 42;
if
(
smallNumberInt
== 42)
System.
out
.println(
"1."
);
final
Integer
smallNumberInteger
= Integer.valueOf(
42
);
if
(
smallNumberInteger
== (Object) 42)
System.
out
.println(
"2."
);
final int
largeNumberInt
= 500;
if
(
largeNumberInt
== 500)
System.
out
.println(
"3."
);
final
Integer
largeNumberInteger
= Integer.valueOf(
500
);
if
(
largeNumberInteger
== (Object) 500)
System.
out
.println(
"4."
);
}
{
final int
value
= 42;
final
Vector
v
=
new
Vector();
v
.add(
value
);
System.
out
.println(
"first = "
+
v
.getFirst().getClass());
Main.f(
value
,
false
);
}
private static void
f(
final
Object
a
,
final boolean
b
) {
System.
out
.println(
"f(Object a, boolean b)"
);
}
private static void
f(
final
Object
a
,
final
Object
b
) {
System.
out
.println(
"f(Object a, Object b)"
);
}
Prints
1.
2.
3.

73/172
(Gotchas) try
{final
Integer
a
=
null
;
System.
out
.println(
"a = "
+
a
);
final int
b
=
a
;
System.
out
.println(
"b = "
+
b
);
}
catch
(
final
NullPointerException
e
) {
}
{
final
ResultSet
rs
=
this
.doSomeDatabaseQuery();
final
Double
value
=
rs
.getDouble(
"someDoubleField"
);
}
{
final
Integer
i
=
new
Integer(1);
final
Double
d
=
new
Double(2.0);
System.
out
.println(
"i = "
+
i
);
System.
out
.println(
"d = "
+
d
);
final
Object
o1
=
i
;
System.
out
.println(
"o1 = "
+
o1
);
final
Object
o2
=
true
?
i
:
d
;
System.
out
.println(
"o2 = "
+
o2
);
System.
out
.println(
o1
.equals(
o2
));
}
{
final int
smallNumberInt
= 42;
if
(
smallNumberInt
== 42)
System.
out
.println(
"1."
);
final
Integer
smallNumberInteger
= Integer.valueOf(
42
);
if
(
smallNumberInteger
== (Object) 42)
System.
out
.println(
"2."
);
final int
largeNumberInt
= 500;
if
(
largeNumberInt
== 500)
System.
out
.println(
"3."
);
final
Integer
largeNumberInteger
= Integer.valueOf(
500
);
if
(
largeNumberInteger
== (Object) 500)
System.
out
.println(
"4."
);
}
{
final int
value
= 42;
final
Vector
v
=
new
Vector();
v
.add(
value
);
System.
out
.println(
"first = "
+
v
.getFirst().getClass());
Main.f(
value
,
false
);
}
private static void
f(
final
Object
a
,
final boolean
b
) {
System.
out
.println(
"f(Object a, boolean b)"
);
}
private static void
f(
final
Object
a
,
final
Object
b
) {
System.
out
.println(
"f(Object a, Object b)"
);
}

74/172
(Gotchas) try
{final
Integer
a
=
null
;
System.
out
.println(
"a = "
+
a
);
final int
b
=
a
;
System.
out
.println(
"b = "
+
b
);
}
catch
(
final
NullPointerException
e
) {
}
{
final
ResultSet
rs
=
this
.doSomeDatabaseQuery();
final
Double
value
=
rs
.getDouble(
"someDoubleField"
);
}
{
final
Integer
i
=
new
Integer(1);
final
Double
d
=
new
Double(2.0);
System.
out
.println(
"i = "
+
i
);
System.
out
.println(
"d = "
+
d
);
final
Object
o1
=
i
;
System.
out
.println(
"o1 = "
+
o1
);
final
Object
o2
=
true
?
i
:
d
;
System.
out
.println(
"o2 = "
+
o2
);
System.
out
.println(
o1
.equals(
o2
));
}
{
final int
smallNumberInt
= 42;
if
(
smallNumberInt
== 42)
System.
out
.println(
"1."
);
final
Integer
smallNumberInteger
= Integer.valueOf(
42
);
if
(
smallNumberInteger
== (Object) 42)
System.
out
.println(
"2."
);
final int
largeNumberInt
= 500;
if
(
largeNumberInt
== 500)
System.
out
.println(
"3."
);
final
Integer
largeNumberInteger
= Integer.valueOf(
500
);
if
(
largeNumberInteger
== (Object) 500)
System.
out
.println(
"4."
);
}
{
final int
value
= 42;
final
Vector
v
=
new
Vector();
v
.add(
value
);
System.
out
.println(
"first = "
+
v
.getFirst().getClass());
Main.f(
value
,
false
);
}
private static void
f(
final
Object
a
,
final boolean
b
) {
System.
out
.println(
"f(Object a, boolean b)"
);
}
private static void
f(
final
Object
a
,
final
Object
b
) {
System.
out
.println(
"f(Object a, Object b)"
);
}
The method
f(Object,
boolean)is ambiguous

75/172
(Gotchas) try
{final
Integer
a
=
null
;
System.
out
.println(
"a = "
+
a
);
final int
b
=
a
;
System.
out
.println(
"b = "
+
b
);
}
catch
(
final
NullPointerException
e
) {
}
{
final
ResultSet
rs
=
this
.doSomeDatabaseQuery();
final
Double
value
=
rs
.getDouble(
"someDoubleField"
);
}
{
final
Integer
i
=
new
Integer(1);
final
Double
d
=
new
Double(2.0);
System.
out
.println(
"i = "
+
i
);
System.
out
.println(
"d = "
+
d
);
final
Object
o1
=
i
;
System.
out
.println(
"o1 = "
+
o1
);
final
Object
o2
=
true
?
i
:
d
;
System.
out
.println(
"o2 = "
+
o2
);
System.
out
.println(
o1
.equals(
o2
));
}
{
final int
smallNumberInt
= 42;
if
(
smallNumberInt
== 42)
System.
out
.println(
"1."
);
final
Integer
smallNumberInteger
= Integer.valueOf(
42
);
if
(
smallNumberInteger
== (Object) 42)
System.
out
.println(
"2."
);
final int
largeNumberInt
= 500;
if
(
largeNumberInt
== 500)
System.
out
.println(
"3."
);
final
Integer
largeNumberInteger
= Integer.valueOf(
500
);
if
(
largeNumberInteger
== (Object) 500)
System.
out
.println(
"4."
);
}
{
final int
value
= 42;
final
Vector
v
=
new
Vector();
v
.add(
value
);
System.
out
.println(
"first = "
+
v
.getFirst().getClass());
Main.f(
value
,
false
);
}
private static void
f(
final
Object
a
,
final boolean
b
) {
System.
out
.println(
"f(Object a, boolean b)"
);
}
private static void
f(
final
Object
a
,
final
Object
b
) {
System.
out
.println(
"f(Object a, Object b)"
);
}

76/172
Root Cause 
Identity
– All instances (and all
classes) are uniquely
identified

77/172
Root Cause 
Identity
– All instances (and all
classes) are uniquely
identified
final int
i1
= 42;
final int
j1
= 42;
System.
out
.println(
i1
==
j1
);
final
Integer
i2
= Integer.valueOf(42);
final
Integer
j2
= Integer.valueOf(
"42"
);
System.
out
.println(
i2
==
j2
);
System.
out
.println(System.identityHashCode(
i2
));
System.
out
.println(System.identityHashCode(
j2
));
final
String
s1
=
"Hello, World!"
;
final
String
s2
=
"Hello, Wordl!"
;
System.
out
.println(
s1
==
s2
);
final
ClassLoader
cl1
= Main.
class
.getClassLoader();
final
Class<?>
c1
=
cl1
.loadClass(
"net.....Main"
);
final
ClassLoader
cl2
= Main.
class
.getClassLoader();
final
Class<?>
c2
=
cl2
.loadClass(
"net.....Main"
);
final
MyClassLoader
cl3
=
new
MyClassLoader();
final
Class<?>
c3
=
cl3
.findClass(
"net.....Main"
);
System.
out
.println(
c1
==
c2
);
System.
out
.println(
c1
==
c3
);

78/172
Root Cause 
Identity
– All instances (and all
classes) are uniquely
identified
final int
i1
= 42;
final int
j1
= 42;
System.
out
.println(
i1
==
j1
);
final
Integer
i2
= Integer.valueOf(42);
final
Integer
j2
= Integer.valueOf(
"42"
);
System.
out
.println(
i2
==
j2
);
System.
out
.println(System.identityHashCode(
i2
));
System.
out
.println(System.identityHashCode(
j2
));
final
String
s1
=
"Hello, World!"
;
final
String
s2
=
"Hello, Wordl!"
;
System.
out
.println(
s1
==
s2
);
final
ClassLoader
cl1
= Main.
class
.getClassLoader();
final
Class<?>
c1
=
cl1
.loadClass(
"net.....Main"
);
final
ClassLoader
cl2
= Main.
class
.getClassLoader();
final
Class<?>
c2
=
cl2
.loadClass(
"net.....Main"
);
final
MyClassLoader
cl3
=
new
MyClassLoader();
final
Class<?>
c3
=
cl3
.findClass(
"net.....Main"
);
System.
out
.println(
c1
==
c2
);
System.
out
.println(
c1
==
c3
);
true
true
617901222
617901222
false
true
false

79/172
Solution 
Identity-less instances
–Value classes
–Value objects
“Codes like a class, works like an int.”

80/172
Value Classes public value class
Substring
implements
CharSequence {
private
String
str
;
private int
start
;
private int
end
;
public
Substring(
final
String
str
,
final int
start
,
final int
end
) {
Substring.checkBounds(
start
,
end
,
str
.length());
this
.
str
=
str
;
this
.
start
=
start
;
this
.
end
=
end
;
}
public int
length() {
return this
.
end
-
this
.
start
;
}
public char
charAt(
final int
i
) {
Substring.checkBounds(0,
i
, length());
return
str
.charAt(
start
+
i
);
}
public
Substring subSequence(
final int
s
,
final int
e
) {
Substring.checkBounds(
s
,
e
, length());
return new
Substring(
str
,
start
+
s
,
start
+
e
);
}
public
String toString() {
return
str
.substring(
start
,
end
);
}
private static void
checkBounds(
final int
start
,
final int
end
,
final int
length
) {
if
(
start
< 0 ||
end
<
start
||
length
<
end
) {
throw new
IndexOutOfBoundsException();
}
}
}

81/172
Value Classes public value class
Substring
implements
CharSequence {
private
String
str
;
private int
start
;
private int
end
;
public
Substring(
final
String
str
,
final int
start
,
final int
end
) {
Substring.checkBounds(
start
,
end
,
str
.length());
this
.
str
=
str
;
this
.
start
=
start
;
this
.
end
=
end
;
}
public int
length() {
return this
.
end
-
this
.
start
;
}
public char
charAt(
final int
i
) {
Substring.checkBounds(0,
i
, length());
return
str
.charAt(
start
+
i
);
}
public
Substring subSequence(
final int
s
,
final int
e
) {
Substring.checkBounds(
s
,
e
, length());
return new
Substring(
str
,
start
+
s
,
start
+
e
);
}
public
String toString() {
return
str
.substring(
start
,
end
);
}
private static void
checkBounds(
final int
start
,
final int
end
,
final int
length
) {
if
(
start
< 0 ||
end
<
start
||
length
<
end
) {
throw new
IndexOutOfBoundsException();
}
}
}
New keyword

82/172
Value Classes public value class
Substring
implements
CharSequence {
private
String
str
;
private int
start
;
private int
end
;
public
Substring(
final
String
str
,
final int
start
,
final int
end
) {
Substring.checkBounds(
start
,
end
,
str
.length());
this
.
str
=
str
;
this
.
start
=
start
;
this
.
end
=
end
;
}
public int
length() {
return this
.
end
-
this
.
start
;
}
public char
charAt(
final int
i
) {
Substring.checkBounds(0,
i
, length());
return
str
.charAt(
start
+
i
);
}
public
Substring subSequence(
final int
s
,
final int
e
) {
Substring.checkBounds(
s
,
e
, length());
return new
Substring(
str
,
start
+
s
,
start
+
e
);
}
public
String toString() {
return
str
.substring(
start
,
end
);
}
private static void
checkBounds(
final int
start
,
final int
end
,
final int
length
) {
if
(
start
< 0 ||
end
<
start
||
length
<
end
) {
throw new
IndexOutOfBoundsException();
}
}
}

83/172
Value Classes public value class
Substring
implements
CharSequence {
private
String
str
;
private int
start
;
private int
end
;
public
Substring(
final
String
str
,
final int
start
,
final int
end
) {
Substring.checkBounds(
start
,
end
,
str
.length());
this
.
str
=
str
;
this
.
start
=
start
;
this
.
end
=
end
;
}
public int
length() {
return this
.
end
-
this
.
start
;
}
public char
charAt(
final int
i
) {
Substring.checkBounds(0,
i
, length());
return
str
.charAt(
start
+
i
);
}
public
Substring subSequence(
final int
s
,
final int
e
) {
Substring.checkBounds(
s
,
e
, length());
return new
Substring(
str
,
start
+
s
,
start
+
e
);
}
public
String toString() {
return
str
.substring(
start
,
end
);
}
private static void
checkBounds(
final int
start
,
final int
end
,
final int
length
) {
if
(
start
< 0 ||
end
<
start
||
length
<
end
) {
throw new
IndexOutOfBoundsException();
}
}
}
Method call
before super()

84/172
Value Classes public value class
Substring
implements
CharSequence {
private
String
str
;
private int
start
;
private int
end
;
public
Substring(
final
String
str
,
final int
start
,
final int
end
) {
Substring.checkBounds(
start
,
end
,
str
.length());
this
.
str
=
str
;
this
.
start
=
start
;
this
.
end
=
end
;
}
public int
length() {
return this
.
end
-
this
.
start
;
}
public char
charAt(
final int
i
) {
Substring.checkBounds(0,
i
, length());
return
str
.charAt(
start
+
i
);
}
public
Substring subSequence(
final int
s
,
final int
e
) {
Substring.checkBounds(
s
,
e
, length());
return new
Substring(
str
,
start
+
s
,
start
+
e
);
}
public
String toString() {
return
str
.substring(
start
,
end
);
}
private static void
checkBounds(
final int
start
,
final int
end
,
final int
length
) {
if
(
start
< 0 ||
end
<
start
||
length
<
end
) {
throw new
IndexOutOfBoundsException();
}
}
}

85/172
Value Classes 
Cannot compile with Eclipse
–Or any other current IDEs?
$ javac --enable-preview -source 23 -Xlint:preview -d ../bin/ net/ptidej/valhalla/valueclass/Substring.java
net\ptidej\valhalla\valueclass\Substring.java:3: warning:
[preview] value classes are a preview feature and may be removed in a future release.
public value class Substring implements CharSequence {
^
net\ptidej\valhalla\valueclass\Substring.java:3: warning:
[preview] value classes are a preview feature and may be removed in a future release.
public value class Substring implements CharSequence {
^
net\ptidej\valhalla\valueclass\Substring.java:8: warning:
[preview] statements before super() is a preview feature and may be removed in a future release.
public Substring(final String str, final int start, final int end) {
^
3 warnings

86/172
Value Classes 
The class is implicitly final […]

All instance fields are implicitly final […]

The class does not extend an identityclass
or an identityinterface

All constructors are implicitly regulated, […],
limiting use of this[…]

No instance methods are […] synchronised

(Possibly) The class does not declare a
finalize()method

87/172
Value Classes public static void
main(
final
String[]
args
) {
final
Substring
subs1
=
new
Substring(
"Hello, World!"
, 7, 13);
System.
out
.println(
subs1
);
final
Substring
subs2
=
new
Substring(
"Hello, World!"
, 7, 13);
System.
out
.println(
subs1
);
System.
out
.println(Modifier.isIdentity(Substring.
class
.getModifiers()));
System.
out
.println(
subs1
==
subs2
);
}

88/172
Value Classes
World!
World!
false
true
public static void
main(
final
String[]
args
) {
final
Substring
subs1
=
new
Substring(
"Hello, World!"
, 7, 13);
System.
out
.println(
subs1
);
final
Substring
subs2
=
new
Substring(
"Hello, World!"
, 7, 13);
System.
out
.println(
subs1
);
System.
out
.println(Modifier.isIdentity(Substring.
class
.getModifiers()));
System.
out
.println(
subs1
==
subs2
);
}

89/172
Value and Identity public identity interface
ICounter {
int
getValue();
void
increment();
}
public value interface
IJSONValue {
String toJsonString();
}

90/172
Value and Identity public identity interface
ICounter {
int
getValue();
void
increment();
}
public value interface
IJSONValue {
String toJsonString();
}
$ javac --enable-preview -source 23 -Xlint:preview -d ../bin/ net/ptidej/valhalla/valueclass/ICounter.java
net\ptidej\valhalla\valueclass\ICounter.java:3: error: class, interface, enum, or record expected
public identity interface ICounter {
^
1 error
$ javac --enable-preview -source 23 -Xlint:preview -d ../bin/ net/ptidej/valhalla/valueclass/IJSONValue.java
net\ptidej\valhalla\valueclass\IJSONValue.java:3: warning:
[preview] value classes are a preview feature and may be removed in a future release.
public value interface IJSONValue {
^
net\ptidej\valhalla\valueclass\IJSONValue.java:3: warning:
[preview] value classes are a preview feature and may be removed in a future release.
public value interface IJSONValue {
^
net\ptidej\valhalla\valueclass\IJSONValue.java:3: error: illegal combination of modifiers: value and interface
public value interface IJSONValue {
^
1 error
2 warnings

91/172
Value and Identity public identity interface
ICounter {
int
getValue();
void
increment();
}
public value interface
IJSONValue {
String toJsonString();
}
$ javac --enable-preview -source 23 -Xlint:preview -d ../bin/ net/ptidej/valhalla/valueclass/ICounter.java
net\ptidej\valhalla\valueclass\ICounter.java:3: error: class, interface, enum, or record expected
public identity interface ICounter {
^
1 error $ javac --enable-preview -source 23 -Xlint:preview -d ../bin/ net/ptidej/valhalla/valueclass/IJSONValue.java
net\ptidej\valhalla\valueclass\IJSONValue.java:3: warning:
[preview] value classes are a preview feature and may be removed in a future release.
public value interface IJSONValue {
^
net\ptidej\valhalla\valueclass\IJSONValue.java:3: warning:
[preview] value classes are a preview feature and may be removed in a future release.
public value interface IJSONValue {
^
net\ptidej\valhalla\valueclass\IJSONValue.java:3: error: illegal combination of modifiers: value and interface
public value interface IJSONValue {
^
1 error 2 warnings

92/172
Value and Identity public identity interface
ICounter {
int
getValue();
void
increment();
}
public value interface
IJSONValue {
String toJsonString();
}
$ javac --enable-preview -source 23 -Xlint:preview -d ../bin/ net/ptidej/valhalla/valueclass/ICounter.java
net\ptidej\valhalla\valueclass\ICounter.java:3: error: class, interface, enum, or record expected
public identity interface ICounter {
^
1 error $ javac --enable-preview -source 23 -Xlint:preview -d ../bin/ net/ptidej/valhalla/valueclass/IJSONValue.java
net\ptidej\valhalla\valueclass\IJSONValue.java:3: warning:
[preview] value classes are a preview feature and may be removed in a future release.
public value interface IJSONValue {
^
net\ptidej\valhalla\valueclass\IJSONValue.java:3: warning:
[preview] value classes are a preview feature and may be removed in a future release.
public value interface IJSONValue {
^
net\ptidej\valhalla\valueclass\IJSONValue.java:3: error: illegal combination of modifiers: value and interface
public value interface IJSONValue {
^
1 error 2 warnings
Not yet implemented

93/172
Value and Identity 
By default, an interface may be implemented
by both value classes and identity classes

[If an] interface is only meant for one kind of
class or the other

“It is an error for a value class or interface to
extend an identity class or interface […]”
public identity interface
ICounter {
int
getValue();
void
increment();
}
public value interface
IJSONValue {
String toJsonString();
}

94/172
Value and Identity 
By default, an interface may be implemented
by both value classes and identity classes

[If an] interface is only meant for one kind of
class or the other

“It is an error for a value class or interface to
extend an identity class or interface […]”
public identity interface
ICounter {
int
getValue();
void
increment();
}
public value interface
IJSONValue {
String toJsonString();
}
New keywords

95/172
Value and Identity 
Special considerations
–A functional interface, compatible with lambda
expressions, must allow for both value and
identity implementations
–An abstract class must allow for both value
classes and identity classes by default
–The class Objectis special
• A concrete class
• Not an identity class
• Supports both identity and value subclasses

96/172
Regulated Constructors 
Compiler error
–Reading an instance field of the class
–Invoking an instance method of the class
–Using
this
, except in an assignment
–Using
super
to access a field or method
–Instantiating an inner class with
this
as
enclosing instance
–Calling explicitly a non-regulated constructor
(
super()
or
this()
)

97/172
Regulated Constructors 
Compiler error
–Reading an instance field of the class
–Invoking an instance method of the class
–Using
this
, except in an assignment
–Using
super
to access a field or method
–Instantiating an inner class with
this
as
enclosing instance
–Calling explicitly a non-regulated constructor
(
super()
or
this()
)
Weaker than the pre-
construction context, itself
weaker than the static context

98/172
Constructor Contexts 
Static
– “The purpose of a static context is to demarcate c ode that must not
refer explicitly or implicitly to the current insta nce of the class whose
declaration lexically encloses the static context. for which there is no
current instance defined of the class whose declara tion lexically
encloses the static context.”

Pre-construction
– “Unlike in a static context, an expression in a pr e-construction
context is free, for example, to refer to the type of the instance under
construction.”

Regulated
– “[A] constructor must not make any use of this in its body, except to
write to an instance field.”
https://docs.oracle.com/en/java/javase/22/docs/specs/stateme nts-before-super-jls.html
https://openjdk.org/jeps/8277163

99/172
Constructor Contexts class
A {
}
class
B
extends
A {
private
String
s
;
private int
i
;
static
{
System.
out
.println(
"Loading of B..."
);
}
{
System.
out
.println(
"Building of a B..."
);
this
.
s
=
"Omega"
;
}
B(
final int
a
) {
System.out
.println(
a
);
this
.
s
=
"Alpha"
;
super
();
this
.
i
=
a
;
}
@Override public
String toString() {
return this
.
s
+
" "
+
this
.
i
;
}
}

100/172
Constructor Contexts class
A {
}
class
B
extends
A {
private
String
s
;
private int
i
;
static
{
System.
out
.println(
"Loading of B..."
);
}
{
System.
out
.println(
"Building of a B..."
);
this
.
s
=
"Omega"
;
}
B(
final int
a
) {
System.out
.println(
a
);
this
.
s
=
"Alpha"
;
super
();
this
.
i
=
a
;
}
@Override public
String toString() {
return this
.
s
+
" "
+
this
.
i
;
}
}
Static

101/172
Constructor Contexts class
A {
}
class
B
extends
A {
private
String
s
;
private int
i
;
static
{
System.
out
.println(
"Loading of B..."
);
}
{
System.
out
.println(
"Building of a B..."
);
this
.
s
=
"Omega"
;
}
B(
final int
a
) {
System.out
.println(
a
);
this
.
s
=
"Alpha"
;
super
();
this
.
i
=
a
;
}
@Override public
String toString() {
return this
.
s
+
" "
+
this
.
i
;
}
}
Static Pre-construction

102/172
Constructor Contexts class
A {
}
class
B
extends
A {
private
String
s
;
private int
i
;
static
{
System.
out
.println(
"Loading of B..."
);
}
{
System.
out
.println(
"Building of a B..."
);
this
.
s
=
"Omega"
;
}
B(
final int
a
) {
System.out
.println(
a
);
this
.
s
=
"Alpha"
;
super
();
this
.
i
=
a
;
}
@Override public
String toString() {
return this
.
s
+
" "
+
this
.
i
;
}
}
Static Pre-construction Regulated

103/172
Constructor Contexts class
A {
}
class
B
extends
A {
private
String
s
;
private int
i
;
static
{
System.
out
.println(
"Loading of B..."
);
}
{
System.
out
.println(
"Building of a B..."
);
this
.
s
=
"Omega"
;
}
B(
final int
a
) {
System.out
.println(
a
);
this
.
s
=
"Alpha"
;
super
();
this
.
i
=
a
;
}
@Override public
String toString() {
return this
.
s
+
" "
+
this
.
i
;
}
}
final
B
b
=
new
B(42);
System.
out
.println(
b
);
Static Pre-construction Regulated

104/172
Constructor Contexts class
A {
}
class
B
extends
A {
private
String
s
;
private int
i
;
static
{
System.
out
.println(
"Loading of B..."
);
}
{
System.
out
.println(
"Building of a B..."
);
this
.
s
=
"Omega"
;
}
B(
final int
a
) {
System.out
.println(
a
);
this
.
s
=
"Alpha"
;
super
();
this
.
i
=
a
;
}
@Override public
String toString() {
return this
.
s
+
" "
+
this
.
i
;
}
}
final
B
b
=
new
B(42);
System.
out
.println(
b
);
Loading of B...
42
Building of a B...
Omega 42Static Pre-construction Regulated

105/172
Constructor Contexts 
Must enable preview features of Java
– javac --enable-preview -source 23 -cp
../bin/ -d ../bin/
net/ptidej/isthmus/constructor/contexts/*
– java --enable-preview
net.ptidej.isthmus.constructor.contexts.
Main

106/172
Caveats 
The ==operator may treat two instances as the same,
where previously they were considered different 
Attempts to synchronize on an instance will fail, either a t
compile time or run time 
The results of toString(), equals(), and hashCode(), if not
overridden, may change 
Assumptions about unique ownership of an instance may
be violated (e.g., an identical instance may be created a t
two different times)

Performance will generally improve, but may have
surprising different characteristics

107/172
Project Babylon

108/172

Thanks to
Paul Sandoz
Juan Fumero
For their code and their help

109/172
Foreign Programming Models 
SQL

GPUs

Machine learning models

Differentiable programming

110/172
Example
f(x, y) = x×(-sin(x×y) + y) ×4

111/172
Example
f(x, y) = x×(-sin(x×y) + y) ×4
∂f(x, y)/∂x = (-sin(x×y) + y
-x×cos(x×y) ×y) ×4

112/172
Requirements 

113/172
Requirements 
Model of Java code

114/172
Requirements 
Model of Java code

API to manipulate such model

115/172
Requirements 
Model of Java code

API to manipulate such model

Interpreter to evaluate such model

116/172
Requirements 
Model of Java code

API to manipulate such model

Interpreter to evaluate such model

117/172
Requirements 
Model of Java code

API to manipulate such model

Interpreter to evaluate such model
= Code Reflection

118/172
Enabling Code Reflection 
As of today
–Don’t even try on Windows
• Even with CygWin…
–Ubuntu 24.04.2 LTS x86_64
> sudo apt-get install autoconf libasound2-dev libcups2-dev libfontconfig1-dev
libx11-dev libxext-dev libxrender-dev libxrandr-dev libxtst-dev libxt-dev
> sudo apt-get install sdkman
> sdk install java 23-open
> sdk use java 23-open
> git clone https://github.com/openjdk/babylon.git
> bash configure --with-boot-jdk=${JAVA_HOME}
> make images
> export JAVA_HOME=$ROOT_BABYLON/babylon/build/linux-x86_64-server-release/jdk
> export PATH=$JAVA_HOME/bin:$PATH
https://jjfumero.github.io/posts/2025/02/07/babylon-an d-tornadovm

119/172
Enabling Code Reflection 
New javac/javaversions
> java -version
openjdk version "24-internal" 2025-03-18
OpenJDK Runtime Environment (build 24-internal-adhoc.guehenyg.babylon)
OpenJDK 64-bit Server VN (build 24-internal-adhoc.guehenyg.babylon, mixed mode)

120/172
Requirements 
Model of Java code

API to manipulate such model

Interpreter to evaluate such model

121/172
Code (Meta-)Model

122/172
Code Model @
CodeReflection
public static double
sub(
final double
a
,
final double
b
) {
return
a
-
b
;
}
final
Method
subMethod
= Main.
class
.getDeclaredMethod(
"sub"
,
double
.
class
,
double
.
class
);
System.out.println(
subMethod
);
final
CoreOp.FuncOp
funcOp
= Op.ofMethod(
subMethod
).get();
System.out.println(
funcOp
.toText());
funcOp
.traverse(
null
, (acc, codeElement) -> {
int
depth = 0;
CodeElement<?, ?> parent = codeElement;
while
((parent = parent.parent()) !=
null
) {
depth++;
}
System.out.println(
" "
.repeat(depth) + codeElement.getClass());
return
acc;
});

123/172
Code Model @
CodeReflection
public static double
sub(
final double
a
,
final double
b
) {
return
a
-
b
;
}
class jdk.incubator.code.op.CoreOp$FuncOp
class jdk.incubator.code.Body
class jdk.incubator.code.Block
class jdk.incubator.code.op.CoreOp$VarOp
class jdk.incubator.code.op.CoreOp$VarOp
class jdk.incubator.code.op.CoreOp$VarAccessOp$VarLoadOp
class jdk.incubator.code.op.CoreOp$VarAccessOp$VarLoadOp
class jdk.incubator.code.op.CoreOp$SubOp
class jdk.incubator.code.op.CoreOp$ReturnOp

124/172
Requirements 
Model of Java code

API to manipulate such model

Interpreter to evaluate such model

125/172
API for Code Models 
Code models only exist for method
annotated with @CodeReflection
@CodeReflection public static double
sub(
final double
a
,
final double
b
) {
return
a
-
b
;
}

126/172
API for Code Models Without @CodeReflection 
Size: 2,633 bytes
With @CodeReflection

Size: 3,437 bytes
public static double sub(double, double);
descriptor: (DD)D
flags: (0x0009) ACC_PUBLIC, ACC_STATIC
Code:
stack=4, locals=4, args_size=2
0: dload_0
1: dload_2
2: dsub
3: dreturn
LineNumberTable:
line 35: 0
public static double sub(double, double);
descriptor: (DD)D
flags: (0x0009) ACC_PUBLIC, ACC_STATIC
Code:
stack=4, locals=4, args_size=2
0: dload_0
1: dload_2
2: dsub
3: dreturn
LineNumberTable:
line 35: 0
RuntimeVisibleAnnotations:
0: #109()
jdk.incubator.code.CodeReflection

127/172
API for Code Models Without @CodeReflection 
Size: 2,633 bytes
With @CodeReflection

Size: 3,437 bytes
public static double sub(double, double);
descriptor: (DD)D
flags: (0x0009) ACC_PUBLIC, ACC_STATIC
Code:
stack=4, locals=4, args_size=2
0: dload_0
1: dload_2
2: dsub
3: dreturn
LineNumberTable:
line 35: 0
public static double sub(double, double);
descriptor: (DD)D
flags: (0x0009) ACC_PUBLIC, ACC_STATIC
Code:
stack=4, locals=4, args_size=2
0: dload_0
1: dload_2
2: dsub
3: dreturn
LineNumberTable:
line 35: 0
RuntimeVisibleAnnotations:
0: #109()
jdk.incubator.code.CodeReflection

128/172
API for Code Models With @CodeReflection 
Size: 3,437 bytes
public static jdk.incubator.code.op.CoreOp$FuncOp
op$net$ptidej$babylon$a$traversal$Main::sub(double, double)double();
descriptor: ()Ljdk/incubator/code/op/CoreOp$FuncOp;
flags: (0x1009) ACC_PUBLIC, ACC_STATIC, ACC_SYNTHETIC
Code:
stack=1, locals=0, args_size=0
0: ldc #1
// String func @\"sub\" @loc=\"33:2:[...]/Main.java\" (%0 : double, %1 : double)double ->
{ %2 : Var<double> = var %0 @\"a\" @loc=\"33:2\"; %3 : Var<double> = var %1
@\"b\" @loc=\"33:2\";\n %4 : double = var.load %2 @loc=\"35:10\";\n %5 : double =
var.load %3 @loc=\"35:14\"; %6 : double = sub %4 %5 @loc=\"35:10\"; return %6
@loc=\"35:3\";\n};
2: invokestatic #3
// Method jdk/incubator/code/parser/OpParser.fromStringOfFuncOp:
(Ljava/lang/String;)Ljdk/incubator/code/Op;
5: checkcast #9
// class jdk/incubator/code/op/CoreOp$FuncOp
8: areturn
LineNumberTable:
line 1: 0

129/172
API for Code Models With @CodeReflection 
Size: 3,437 bytes
public static jdk.incubator.code.op.CoreOp$FuncOp op$net$ptidej$babylon$a$traversal$Main::sub(double, double)double()
;
descriptor: ()Ljdk/incubator/code/op/CoreOp$FuncOp;
flags: (0x1009)
ACC_PUBLIC, ACC_STATIC, ACC_SYNTHETIC
Code:
stack=1, locals=0, args_size=0
0: ldc #1 // String func @\"sub\" @loc=\"33:2:[...]/Main.java\" (%0 : double, %1 : double)double ->
{ %2 : Var<double> = var %0 @\"a\" @loc=\"33:2\"; %3 : Var<double> = var %1
@\"b\" @loc=\"33:2\";\n %4 : double = var.load %2 @loc=\"35:10\";\n %5 : double =
var.load %3 @loc=\"35:14\"; %6 : double = sub %4 %5 @loc=\"35:10\"; return %6
@loc=\"35:3\";\n};
2: invokestatic #3
// Method jdk/incubator/code/parser/OpParser.fromStringOfFuncOp:
(Ljava/lang/String;)Ljdk/incubator/code/Op;
5: checkcast #9
// class jdk/incubator/code/op/CoreOp$FuncOp
8: areturn
LineNumberTable:
line 1: 0

130/172
API for Code Models With @CodeReflection 
Size: 3,437 bytes
public static jdk.incubator.code.op.CoreOp$FuncOp op$net$ptidej$babylon$a$traversal$Main::sub(double, double)double()
;
descriptor: ()Ljdk/incubator/code/op/CoreOp$FuncOp;
flags: (0x1009)
ACC_PUBLIC, ACC_STATIC, ACC_SYNTHETIC
Code:
stack=1, locals=0, args_size=0
0: ldc #1 // String func @\"sub\" @loc=\"33:2:[...]/Main.java\" (%0 : double, %1 : double)double ->
{ %2 : Var<double> = var %0 @\"a\" @loc=\"33:2\"; %3 : Var<double> = var %1
@\"b\" @loc=\"33:2\";\n %4 : double = var.load %2 @loc=\"35:10\";\n %5 : double =
var.load %3 @loc=\"35:14\"; %6 : double = sub %4 %5 @loc=\"35:10\"; return %6
@loc=\"35:3\";\n};
2: invokestatic #3
// Method jdk/incubator/code/parser/OpParser.fromStringOfFuncOp:
(Ljava/lang/String;)Ljdk/incubator/code/Op;
5: checkcast #9
// class jdk/incubator/code/op/CoreOp$FuncOp
8: areturn
LineNumberTable:
line 1: 0
Parser of textually -
serialised code models

131/172
API for Code Models final
Method
subMethod
= Main.
class
.getDeclaredMethod(
"sub"
,
double
.
class
,
double
.
class
);
System.out.println(
subMethod
);
final
CoreOp.FuncOp
funcOp
= Op.ofMethod(
subMethod
).get();
System.out.println(
funcOp
.toText());
funcOp
.traverse(
null
, (acc, codeElement) -> {
int
depth = 0;
CodeElement<?, ?> parent = codeElement;
while
((parent = parent.parent()) !=
null
) {
depth++;
}
System.out.println(
" "
.repeat(depth) + codeElement.getClass());
return
acc;
});
@
CodeReflection
public static double
sub(
final double
a
,
final double
b
) {
return
a
-
b
;
}

132/172
final
Method
subMethod
= Main.
class
.getDeclaredMethod(
"sub"
,
double
.
class
,
double
.
class
);
System.out.println(
subMethod
);
final
CoreOp.FuncOp
funcOp
= Op.ofMethod(
subMethod
).get();
System.out.println(
funcOp
.toText());
funcOp
.traverse(
null
, (acc, codeElement) -> {
int
depth = 0;
CodeElement<?, ?> parent = codeElement;
while
((parent = parent.parent()) !=
null
) {
depth++;
}
System.out.println(
" "
.repeat(depth) + codeElement.getClass());
return
acc;
});
@
CodeReflection
public static double
sub(
final double
a
,
final double
b
) {
return
a
-
b
;
}
public static double net.ptidej.babylon.a.traversal.Main.sub(double,double)
func @"sub" @loc="33:2:[...]/Main.java" (%0 : double, %1 : double)double -> {
%2 : Var<double> = var %0 @"a" @loc="33:2";
%3 : Var<double> = var %1 @"b" @loc="33:2";
%4 : double = var.load %2 @loc="35:10";
%5 : double = var.load %3 @loc="35:14";
%6 : double = sub %4 %5 @loc="35:10";
return %6 @loc="35:3";
};

133/172
Requirements 
Model of Java code

API to manipulate such model

Interpreter to evaluate such model

134/172
Interpreter for Code Models package
jdk.incubator.code.interpreter;
public final class
Interpreter {
private
Interpreter() {
}
/**
* Invokes an invokable operation by interpreting the code elements within the
* operations body.
*
<p>
* The sequence of arguments must [consist] of objects corresponding, in order,
* to the invokable operation's
{@link Op.Invokable#parameters() parameters}
. If
* the invokable operation
{@link Op.Invokable#capturedValues() captures values}
* then the sequence of arguments must be appended with objects corresponding,
* in order, to the captured values.
*
*
@param
l the lookup to use for interpreting reflective operations.
*
@param
op the invokeable operation to interpret.
*
@param
args the invokeable's arguments appended with captured arguments, if any.
*
@return
the interpreter result of invokable operation.
*
@param
<T>
the type of Invokable.
*
@throws
InterpreterException if there is a failure to interpret
*
@throws
Throwable if interpretation results in the throwing of an uncaught exception
*/
public static
<T
extends
Op & Op.Invokable> Object invoke(MethodHandles.Lookup
l
, T
op
, Object...
args
) {
// ...

135/172
Interpreter for Code Models 
Yes, an equivalent of eval()!
–JavaScript
–Python

In pure Java!

136/172
Interpreter for Code Models final
Method
distanceMethod
= Main.
class
.getDeclaredMethod(
"distance"
,
double
.
class
,
double
.
class
);
final
CoreOp.FuncOp
distanceFuncOp
= Op.ofMethod(
distanceMethod
).get();
final
Double
resultsInterpreted1
= (Double) Interpreter.invoke(
MethodHandles.lookup(),
distanceFuncOp
, 10, 2);
System.out.println(
resultsInterpreted1
);
final
CoreOp.FuncOp
distanceFuncOpSSA
= SSA.transform(
distanceFuncOp
);
final
Double
resultsInterpreted2
= (Double) Interpreter.invoke(
MethodHandles.lookup(),
distanceFuncOpSSA
, 42, 2);
System.out.println(
resultsInterpreted2
);

137/172
Interpreter for Code Models final
Method
distanceMethod
= Main.
class
.getDeclaredMethod(
"distance"
,
double
.
class
,
double
.
class
);
final
CoreOp.FuncOp
distanceFuncOp
= Op.ofMethod(
distanceMethod
).get();
final
Double
resultsInterpreted1
= (Double) Interpreter.invoke(
MethodHandles.lookup(),
distanceFuncOp
, 10, 2);
System.out.println(
resultsInterpreted1
);
final
CoreOp.FuncOp
distanceFuncOpSSA
= SSA.transform(
distanceFuncOp
);
final
Double
resultsInterpreted2
= (Double) Interpreter.invoke(
MethodHandles.lookup(),
distanceFuncOpSSA
, 42, 2);
System.out.println(
resultsInterpreted2
);
8
40

138/172
Interpreter for Code Models
https://www.pinterest.com/pin/697213586035124567/

139/172
Interpreter for Code Models final
Method
subMethod
= Main.
class
.getDeclaredMethod(
"sub"
,
double
.
class
,
double
.
class
);
final
CoreOp.FuncOp
funcOp1
= Op.ofMethod(
subMethod
).get();
final
Double
resultsInterpreted1
= (Double) Interpreter.invoke(MethodHandles.lookup(),
funcOp1
, 32, 10);
System.out.println(
resultsInterpreted1
);
final
CoreOp.FuncOp
funcOp2
=
funcOp1
.transform((builder, op) -> {
final
CopyContext cc = builder.context();
if
(op
instanceof
CoreOp.SubOp subOp) {
final
Op.Result inputResult = subOp.result();
final
Op.Result lhs = (Op.Result) cc.getProperty(
"beforeLast"
);
final
Op.Result rhs = (Op.Result) cc.getProperty(
"last"
);
final
Op.Result outputResult = builder.op(CoreOp.add(lhs, rhs));
cc.mapValue(inputResult, outputResult);
}
else if
(op
instanceof
CoreOp.VarAccessOp.VarLoadOp varLoadOp) {
final
Op.Result result = builder.op(varLoadOp);
cc.putProperty(
"beforeLast"
, cc.getProperty(
"last"
));
cc.putProperty(
"last"
, result);
}
else
{
builder.op(op);
}
return
builder;
});
final
Double
resultsInterpreted2
= (Double) Interpreter.invoke(MethodHandles.lookup(),
funcOp2
, 32, 10);
System.out.println(
resultsInterpreted2
);

140/172
Interpreter for Code Models final
Method
subMethod
= Main.
class
.getDeclaredMethod(
"sub"
,
double
.
class
,
double
.
class
);
final
CoreOp.FuncOp
funcOp1
= Op.ofMethod(
subMethod
).get();
final
Double
resultsInterpreted1
= (Double) Interpreter.invoke(MethodHandles.lookup(),
funcOp1
, 32, 10);
System.out.println(
resultsInterpreted1
);
final
CoreOp.FuncOp
funcOp2
=
funcOp1
.transform((builder, op) -> {
final
CopyContext cc = builder.context();
if
(op
instanceof
CoreOp.SubOp subOp) {
final
Op.Result inputResult = subOp.result();
final
Op.Result lhs = (Op.Result) cc.getProperty(
"beforeLast"
);
final
Op.Result rhs = (Op.Result) cc.getProperty(
"last"
);
final
Op.Result outputResult = builder.op(CoreOp.add(lhs, rhs));
cc.mapValue(inputResult, outputResult);
}
else if
(op
instanceof
CoreOp.VarAccessOp.VarLoadOp varLoadOp) {
final
Op.Result result = builder.op(varLoadOp);
cc.putProperty(
"beforeLast"
, cc.getProperty(
"last"
));
cc.putProperty(
"last"
, result);
}
else
{
builder.op(op);
}
return
builder;
});
final
Double
resultsInterpreted2
= (Double) Interpreter.invoke(MethodHandles.lookup(),
funcOp2
, 32, 10);
System.out.println(
resultsInterpreted2
);

141/172
Interpreter for Code Models final
Method
subMethod
= Main.
class
.getDeclaredMethod(
"sub"
,
double
.
class
,
double
.
class
);
final
CoreOp.FuncOp
funcOp1
= Op.ofMethod(
subMethod
).get();
final
Double
resultsInterpreted1
= (Double) Interpreter.invoke(MethodHandles.lookup(),
funcOp1
, 32, 10);
System.out.println(
resultsInterpreted1
);
final
CoreOp.FuncOp
funcOp2
=
funcOp1
.transform((builder, op) -> {
final
CopyContext cc = builder.context();
if
(op
instanceof
CoreOp.SubOp subOp) {
final
Op.Result inputResult = subOp.result();
final
Op.Result lhs = (Op.Result) cc.getProperty(
"beforeLast"
);
final
Op.Result rhs = (Op.Result) cc.getProperty(
"last"
);
final
Op.Result outputResult = builder.op(CoreOp.add(lhs, rhs));
cc.mapValue(inputResult, outputResult);
}
else if
(op
instanceof
CoreOp.VarAccessOp.VarLoadOp varLoadOp) {
final
Op.Result result = builder.op(varLoadOp);
cc.putProperty(
"beforeLast"
, cc.getProperty(
"last"
));
cc.putProperty(
"last"
, result);
}
else
{
builder.op(op);
}
return
builder;
});
final
Double
resultsInterpreted2
= (Double) Interpreter.invoke(MethodHandles.lookup(),
funcOp2
, 32, 10);
System.out.println(
resultsInterpreted2
);
22

142/172
Interpreter for Code Models final
Method
subMethod
= Main.
class
.getDeclaredMethod(
"sub"
,
double
.
class
,
double
.
class
);
final
CoreOp.FuncOp
funcOp1
= Op.ofMethod(
subMethod
).get();
final
Double
resultsInterpreted1
= (Double) Interpreter.invoke(MethodHandles.lookup(),
funcOp1
, 32, 10);
System.out.println(
resultsInterpreted1
);
final
CoreOp.FuncOp
funcOp2
=
funcOp1
.transform((builder, op) -> {
final
CopyContext cc = builder.context();
if
(op
instanceof
CoreOp.SubOp subOp) {
final
Op.Result inputResult = subOp.result();
final
Op.Result lhs = (Op.Result) cc.getProperty(
"beforeLast"
);
final
Op.Result rhs = (Op.Result) cc.getProperty(
"last"
);
final
Op.Result outputResult = builder.op(CoreOp.add(lhs, rhs));
cc.mapValue(inputResult, outputResult);
}
else if
(op
instanceof
CoreOp.VarAccessOp.VarLoadOp varLoadOp) {
final
Op.Result result = builder.op(varLoadOp);
cc.putProperty(
"beforeLast"
, cc.getProperty(
"last"
));
cc.putProperty(
"last"
, result);
}
else
{
builder.op(op);
}
return
builder;
});
final
Double
resultsInterpreted2
= (Double) Interpreter.invoke(MethodHandles.lookup(),
funcOp2
, 32, 10);
System.out.println(
resultsInterpreted2
);
22

143/172
Interpreter for Code Models final
Method
subMethod
= Main.
class
.getDeclaredMethod(
"sub"
,
double
.
class
,
double
.
class
);
final
CoreOp.FuncOp
funcOp1
= Op.ofMethod(
subMethod
).get();
final
Double
resultsInterpreted1
= (Double) Interpreter.invoke(MethodHandles.lookup(),
funcOp1
, 32, 10);
System.out.println(
resultsInterpreted1
);
final
CoreOp.FuncOp
funcOp2
=
funcOp1
.transform((builder, op) -> {
final
CopyContext cc = builder.context();
if
(op
instanceof
CoreOp.SubOp subOp) {
final
Op.Result inputResult = subOp.result();
final
Op.Result lhs = (Op.Result) cc.getProperty(
"beforeLast"
);
final
Op.Result rhs = (Op.Result) cc.getProperty(
"last"
);
final
Op.Result outputResult = builder.op(CoreOp.add(lhs, rhs));
cc.mapValue(inputResult, outputResult);
}
else if
(op
instanceof
CoreOp.VarAccessOp.VarLoadOp varLoadOp) {
final
Op.Result result = builder.op(varLoadOp);
cc.putProperty(
"beforeLast"
, cc.getProperty(
"last"
));
cc.putProperty(
"last"
, result);
}
else
{
builder.op(op);
}
return
builder;
});
final
Double
resultsInterpreted2
= (Double) Interpreter.invoke(MethodHandles.lookup(),
funcOp2
, 32, 10);
System.out.println(
resultsInterpreted2
);
22 42

144/172
Example
f(x, y) = x×(-sin(x×y) + y) ×4
∂f(x, y)/∂x = (-sin(x×y) + y
-x×cos(x×y) ×y) ×4

145/172
Example 
Origin
@
CodeReflection
static double
f(
final double
x
,
final double
y
) {
return
x
* (-Math.sin(
x
*
y
) +
y
) * 4.0d;
}
static double
df_dx(
double
x
,
double
y
) {
return
(-Math.sin(
x
*
y
) +
y
-
x
* Math.cos(
x
*
y
) *
y
) * 4.0d;
}

146/172
Example 
Transformation
final
Method
f
= Main.
class
.getDeclaredMethod(
"f"
,
double
.
class
,
double
.
class
);
final
Double
result_f1
= f(2, 3);
System.out.println(
result_f1
);
final
CoreOp.FuncOp
funcOp_f
= Op.ofMethod(
f
).get();
final
CoreOp.FuncOp
funcOp_f_SSA
= SSA.transform(
funcOp_f
);
final
Double
result_f2
= (Double) Interpreter.invoke(MethodHandles.lookup(),
funcOp_f_SSA
, 2, 3);
System.out.println(
result_f2
);
final
Double
result_df_dx1
= df_dx(2, 3);
System.out.println(
result_df_dx1
);
final
Block.Parameter
x
=
funcOp_f_SSA
.body().entryBlock().parameters().get(0);
final
CoreOp.FuncOp
funcOp_df_dx
= ExpressionElimination.eliminate(ForwardDifferentiation.partialDiff(
funcOp_f_SSA
,
x
));
final
Double
result_df_dx2
= (Double) Interpreter.invoke(MethodHandles.lookup(),
funcOp_df_dx
, 2, 3);
System.out.println(
result_df_dx2
);

147/172
Example 
Transformation
final
Method
f
= Main.
class
.getDeclaredMethod(
"f"
,
double
.
class
,
double
.
class
);
final
Double
result_f1
= f(2, 3);
System.out.println(
result_f1
);
final
CoreOp.FuncOp
funcOp_f
= Op.ofMethod(
f
).get();
final
CoreOp.FuncOp
funcOp_f_SSA
= SSA.transform(
funcOp_f
);
final
Double
result_f2
= (Double) Interpreter.invoke(MethodHandles.lookup(),
funcOp_f_SSA
, 2, 3);
System.out.println(
result_f2
);
final
Double
result_df_dx1
= df_dx(2, 3);
System.out.println(
result_df_dx1
);
final
Block.Parameter
x
=
funcOp_f_SSA
.body().entryBlock().parameters().get(0);
final
CoreOp.FuncOp
funcOp_df_dx
=
ExpressionElimination.eliminate
(
ForwardDifferentiation.partialDiff
(
funcOp_f_SSA
,
x
));
final
Double
result_df_dx2
= (Double) Interpreter.invoke(MethodHandles.lookup(),
funcOp_df_dx
, 2, 3);
System.out.println(
result_df_dx2
);

148/172
Example 
Transformation
final
Method
f
= Main.
class
.getDeclaredMethod(
"f"
,
double
.
class
,
double
.
class
);
final
Double
result_f1
= f(2, 3);
System.out.println(
result_f1
);
final
CoreOp.FuncOp
funcOp_f
= Op.ofMethod(
f
).get();
final
CoreOp.FuncOp
funcOp_f_SSA
= SSA.transform(
funcOp_f
);
final
Double
result_f2
= (Double) Interpreter.invoke(MethodHandles.lookup(),
funcOp_f_SSA
, 2, 3);
System.out.println(
result_f2
);
final
Double
result_df_dx1
= df_dx(2, 3);
System.out.println(
result_df_dx1
);
final
Block.Parameter
x
=
funcOp_f_SSA
.body().entryBlock().parameters().get(0);
final
CoreOp.FuncOp
funcOp_df_dx
=
ExpressionElimination.eliminate
(
ForwardDifferentiation.partialDiff
(
funcOp_f_SSA
,
x
));
final
Double
result_df_dx2
= (Double) Interpreter.invoke(MethodHandles.lookup(),
funcOp_df_dx
, 2, 3);
System.out.println(
result_df_dx2
);
The differentiation happens here

149/172
final
Method
f
= Main.
class
.getDeclaredMethod(
"f"
,
double
.
class
,
double
.
class
);
final
Double
result_f1
= f(2, 3);
System.out.println(
result_f1
);
final
CoreOp.FuncOp
funcOp_f
= Op.ofMethod(
f
).get();
final
CoreOp.FuncOp
funcOp_f_SSA
= SSA.transform(
funcOp_f
);
final
Double
result_f2
= (Double) Interpreter.invoke(MethodHandles.lookup(),
funcOp_f_SSA
, 2, 3);
System.out.println(
result_f2
);
final
Double
result_df_dx1
= df_dx(2, 3);
System.out.println(
result_df_dx1
);
final
Block.Parameter
x
=
funcOp_f_SSA
.body().entryBlock().parameters().get(0);
final
CoreOp.FuncOp
funcOp_df_dx
= ExpressionElimination.eliminate(ForwardDifferentiation.partialDiff(
funcOp_f_SSA
,
x
));
final
Double
result_df_dx2
= (Double) Interpreter.invoke(MethodHandles.lookup(),
funcOp_df_dx
, 2, 3);
System.out.println(
result_df_dx2
);
Example 
Results
– f(2, 3) = 2×(-sin(2×3) + 3) ×4
= 26.235323985591407
–∂f(2, 3)/∂x = (-sin(2×3) + 3 -2×cos(2×3) ×3) ×4
= -9.92642488681308

150/172
final
Method
f
= Main.
class
.getDeclaredMethod(
"f"
,
double
.
class
,
double
.
class
);
final
Double
result_f1
= f(2, 3);
System.out.println(
result_f1
);
final
CoreOp.FuncOp
funcOp_f
= Op.ofMethod(
f
).get();
final
CoreOp.FuncOp
funcOp_f_SSA
= SSA.transform(
funcOp_f
);
final
Double
result_f2
= (Double) Interpreter.invoke(MethodHandles.lookup(),
funcOp_f_SSA
, 2, 3);
System.out.println(
result_f2
);
final
Double
result_df_dx1
= df_dx(2, 3);
System.out.println(
result_df_dx1
);
final
Block.Parameter
x
=
funcOp_f_SSA
.body().entryBlock().parameters().get(0);
final
CoreOp.FuncOp
funcOp_df_dx
= ExpressionElimination.eliminate(ForwardDifferentiation.partialDiff(
funcOp_f_SSA
,
x
));
final
Double
result_df_dx2
= (Double) Interpreter.invoke(MethodHandles.lookup(),
funcOp_df_dx
, 2, 3);
System.out.println(
result_df_dx2
);
Example 
Results
– f(2, 3) = 2×(-sin(2×3) + 3) ×4
= 26.235323985591407
–∂f(2, 3)/∂x = (-sin(2×3) + 3 -2×cos(2×3) ×3) ×4
= -9.92642488681308
26.235323985591407
26.235323985591407
-9.92642488681308
-9.92642488681308

151/172
Other Example 
Emulating C# LINQ in Java
–Language INtegrated Query

152/172
DISCUSSIONS

153/172
Questions 
In Java
–How to best open JVM’s closed world?
–How to best bridge memory models?

154/172
Answers 
In Java
–How to best open JVM’s closed world?
• Panama
• Babylon
–How to best bridge memory models?
• Panama
• Valhalla

155/172
The Isthmus in the JVM 1.
Syntax: lambdas vs. function pointers, no C macros, no C++ templates
2.
Naming: naming and scoping
3.
Data types: Booleans, strings, which always have he aders
4.
Storage management: many native libraries operate through pointers
to memory, garbage collection
5.
Exceptions: C++ and Java exceptions behave differently; C APIs
sometimes require ad hoc polling for errors
6.
Semantics: Java strings are immutable while C “stri ngs” are character
arrays, C++ strings are yet different
7.
Performance: strings, boxing, copying cause perform ance “potholes”
8.
Safety: the JVM must continue to operate correctly even in the face of
errors or abuse of any single API
https://cr.openjdk.org/~jrose/panama/isthmus-in-the-vm-2 014.html

156/172
The Isthmus in the JVM 1.
Syntax: lambdas vs. function pointers, no C
macros, no C++ templates 
With project Panama, possible to manipulate
C pointers
https://cr.openjdk.org/~jrose/panama/isthmus-in-the-vm-2 014.html

157/172
The Isthmus in the JVM 2.
Naming: naming and scoping

Nothing much here…
https://cr.openjdk.org/~jrose/panama/isthmus-in-the-vm-2 014.html

158/172
The Isthmus in the JVM 3.
Data types: Booleans, strings, which always
have headers 
With Project Valhalla, possible to create
value classes/objects
https://cr.openjdk.org/~jrose/panama/isthmus-in-the-vm-2 014.html

159/172
The Isthmus in the JVM 4.
Storage management: many native libraries
operate through pointers to memory,
garbage collection

With Project Panama, possible to manipulate
memory from Java
https://cr.openjdk.org/~jrose/panama/isthmus-in-the-vm-2 014.html

160/172
The Isthmus in the JVM 5.
Exceptions: C++ and Java exceptions
behave differently; C APIs sometimes
require ad hoc polling for errors

With Project Babylon, possible to rewrite
code automagically
https://cr.openjdk.org/~jrose/panama/isthmus-in-the-vm-2 014.html

161/172
The Isthmus in the JVM 6.
Semantics: Java strings are immutable
while C “strings” are character arrays, C++
strings are yet different

With Project Babylon, possible to rewrite
code automagically
https://cr.openjdk.org/~jrose/panama/isthmus-in-the-vm-2 014.html

162/172
The Isthmus in the JVM 7.
Performance: strings, boxing, copying
cause performance “potholes” 
With Project Valhalla, possible to have
“primitive” performance
https://cr.openjdk.org/~jrose/panama/isthmus-in-the-vm-2 014.html

163/172
The Isthmus in the JVM 8.
Safety: the JVM must continue to operate
correctly even in the face of errors or abuse
of any single API

With Project Panama, more Java code, less
C code, less risks
https://cr.openjdk.org/~jrose/panama/isthmus-in-the-vm-2 014.html

164/172
Three-prong Approach
https://en.wikipedia.org/wiki/Valhalla
https://www.historyextra.com/period/ancient-history/baby lon-babylonia-tower-babel-hanging-gardens-hammurabi/
https://www.georgeglazer.com/wpmain/product/where-atlantic-pacific-meet-the-panama-canal-to-day-birds-eye-v iew-by-richard-rummell-1914/

165/172
With Such An Approach

166/172
With Such An Approach final
OpenAiChatModel
model
= OpenAiChatModel.builder().apiKey(Main.
API_KEY
)
.modelName(OpenAiChatModelName.
GPT_4_O_MINI
).build();
final
String
answer
=
model
.chat(
"Give me the advantages and disadvantages of Java"
);
System.
out
.println(
answer
);

167/172
With Such An Approach final
OpenAiChatModel
model
= OpenAiChatModel.builder().apiKey(Main.
API_KEY
)
.modelName(OpenAiChatModelName.
GPT_4_O_MINI
).build();
final
String
answer
=
model
.chat(
"Give me the advantages and disadvantages of Java"
);
System.
out
.println(
answer
);
Java is a widely-used programming language known for its versatility, portability, and robust nature. Here are some
advantages and disadvantages of using Java:
### Advantages of Java
1. **Platform Independence**: Java is designed to be platform-independent at both the source and binary levels, thanks
to the Java Virtual Machine (JVM). This allows developers to write code once and run it anywhere (Write Once, Run
Anywhere - WORA).
[...]
8. **Mature Ecosystem**: Java has a mature ecosystem with enterprise-level solutions, making it a preferred choice for
large-scale applications, including web and mobile development.
### Disadvantages of Java
1. **Performance**: Java can be slower than some compiled languages (such as C or C++) due to the overhead of the JVM
and garbage collection, making it less suitable for performance-critical applications.
[...]
8. **Dependence on JVM**: Java applications require the Java Runtime Environment (JRE) to run, which may not be
available in all environments.
In conclusion, Java is a powerful and versatile language with many advantages, particularly in enterprise and cross-
platform applications. However, developers should consider its disadvantages when selecting a programming language for
specific projects.

168/172
With Such An Approach 
Actually…
https://github.com/langchain4j/langchain4j/blob/main/l angchain4j-open-
ai/src/main/java/dev/langchain4j/model/openai/OpenAiChatModel.java
this
.client = OpenAiClient.builder()
.httpClientBuilder(builder.httpClientBuilder)
.baseUrl(getOrDefault(builder.baseUrl, DEFAULT_OPENAI_URL))
.apiKey(builder.apiKey)
.organizationId(builder.organizationId)
.projectId(builder.projectId)
.connectTimeout(getOrDefault(builder.timeout, ofSeconds(15)))
.readTimeout(getOrDefault(builder.timeout, ofSeconds(60)))
.logRequests(getOrDefault(builder.logRequests,
false
))
.logResponses(getOrDefault(builder.logResponses,
false
))
.userAgent(DEFAULT_USER_AGENT)
.customHeaders(builder.customHeaders)
.build();

169/172
With Such An Approach 
Actually…
https://github.com/langchain4j/langchain4j/blob/main/l angchain4j-open-
ai/src/main/java/dev/langchain4j/model/openai/OpenAiChatModel.java
this
.client = OpenAiClient.builder()
.httpClientBuilder(builder.httpClientBuilder)
.baseUrl(getOrDefault(builder.baseUrl, DEFAULT_OPENAI_URL))
.apiKey(builder.apiKey)
.organizationId(builder.organizationId)
.projectId(builder.projectId)
.connectTimeout(getOrDefault(builder.timeout, ofSeconds(15)))
.readTimeout(getOrDefault(builder.timeout, ofSeconds(60)))
.logRequests(getOrDefault(builder.logRequests,
false
))
.logResponses(getOrDefault(builder.logResponses,
false
))
.userAgent(DEFAULT_USER_AGENT)
.customHeaders(builder.customHeaders)
.build();
It’s a REST call!

170/172
With Such An Approach 
Three ways for language interoperability
–REST APIs and such
–Script engines
–FFIs

They have different (dis)advantages!

171/172
With Such An Approach 
REST APIs and such
– Simple
– Slow, duplications 
Script engines
– Complex
– Fast, some duplications 
FFIs
– Convoluted
– Fast, no duplications

172/172
With Such An Approach 
REST APIs and such
– Simple
– Slow, duplications 
Script engines
– Complex
– Fast, some duplications 
FFIs
–Convoluted
–Very fast
, no duplications
With Projects Panama,
Valhalla, and Babylon!