project panama - beyond the (jvm) wall
TRANSCRIPT
https://middleofnowheregaming.files.wordpress.com/2015/04/game-of-thrones_20150327091828.jpg
Project PanamaBeyond the (JVM) Wall
www.hazelcast.com@noctarius2k
DisclaimerThis is not a rant - promised!
Just a little bit about JNI ;-)
www.hazelcast.com@noctarius2k
Disclaimer #2If you haven’t seen Game of Thrones yet
keep your eyes closed!
www.hazelcast.com@noctarius2k
Disclaimer #3Everything is provisional
Don’t take anything as final!
www.hazelcast.com@noctarius2k
Who’s that dude?• Chris Engelbert • Manager of Developer Relations @Hazelcast
• Java-Passionate (10+ years)
• Performance • Garbage Collection • JVM / Benchmark Fairytales
www.hazelcast.com@noctarius2k
I drink and I know things (sometimes)
www.hazelcast.com@noctarius2k
Project Panama
The True Native Love
www.hazelcast.com@noctarius2k
Unite Enemies
C/C++Java
www.hazelcast.com@noctarius2k
JNI! That's a good name for you!
www.hazelcast.com@noctarius2k
JNI brings interaction between native code and Java
#include <unistd.h>int pid = getpid();
simple kernel call
www.hazelcast.com@noctarius2k
JNI brings interaction between native code and Java
#include <unistd.h>int pid = getpid();
simple kernel call header import
www.hazelcast.com@noctarius2k
JNI brings interaction between native code and Java
#include <unistd.h>int pid = getpid();
simple kernel call header import
request PID
www.hazelcast.com@noctarius2k
#include <unistd.h>int pid = getpid();
Isn’t that easy in C?
www.hazelcast.com@noctarius2k
You know nothing, of JNI!
www.hazelcast.com@noctarius2k
Starting with the C part :-)
www.hazelcast.com@noctarius2k
Starting with the C part :-)
extern C { JNIEXPORT int JNICALL Java_ProcessIdentifier_getProcessId(JNIEnv *, jobject);}
www.hazelcast.com@noctarius2k
Starting with the C part :-)
extern C { JNIEXPORT int JNICALL Java_ProcessIdentifier_getProcessId(JNIEnv *, jobject);}
export it as a JNI method
www.hazelcast.com@noctarius2k
Starting with the C part :-)
extern C { JNIEXPORT int JNICALL Java_ProcessIdentifier_getProcessId(JNIEnv *, jobject);}
export it as a JNI method
Java Classname
www.hazelcast.com@noctarius2k
Starting with the C part :-)
extern C { JNIEXPORT int JNICALL Java_ProcessIdentifier_getProcessId(JNIEnv *, jobject);}
export it as a JNI method
Java Classname Java Methodname
www.hazelcast.com@noctarius2k
extern C { JNIEXPORT int JNICALL Java_ProcessIdentifier_getProcessId(JNIEnv *, jobject);}
Starting with the C part :-)
JNIEXPORT int JNICALLJava_ProcessIdentifier_getProcessId(JNIEnv *env, jobject thisObject) { return getpid();}
www.hazelcast.com@noctarius2k
extern C { JNIEXPORT int JNICALL Java_ProcessIdentifier_getProcessId(JNIEnv *, jobject);}
Starting with the C part :-)
JNIEXPORT int JNICALLJava_ProcessIdentifier_getProcessId(JNIEnv *env, jobject thisObject) { return getpid();}
kernel call
www.hazelcast.com@noctarius2k
When you think you just won…
www.hazelcast.com@noctarius2k
extern C { JNIEXPORT int JNICALL Java_ProcessIdentifier_getProcessId(JNIEnv *, jobject);}
JNIEXPORT int JNICALLJava_ProcessIdentifier_getProcessId(JNIEnv *env, jobject thisObject) { return getpid();}
Starting with the C part :-)JNIEXPORT jint JNICALLJNI_OnLoad(JavaVM *vm, void *reserved) { return JNI_VERSION_1_2;}
www.hazelcast.com@noctarius2k
extern C { JNIEXPORT int JNICALL Java_ProcessIdentifier_getProcessId(JNIEnv *, jobject);}
JNIEXPORT int JNICALLJava_ProcessIdentifier_getProcessId(JNIEnv *env, jobject thisObject) { return getpid();}
Starting with the C part :-)JNIEXPORT jint JNICALLJNI_OnLoad(JavaVM *vm, void *reserved) { return JNI_VERSION_1_2;}
JNI version definition
www.hazelcast.com@noctarius2k
extern C { JNIEXPORT int JNICALL Java_ProcessIdentifier_getProcessId(JNIEnv *, jobject);}
JNIEXPORT int JNICALLJava_ProcessIdentifier_getProcessId(JNIEnv *env, jobject thisObject) { return getpid();}
done, easy right?JNIEXPORT jint JNICALLJNI_OnLoad(JavaVM *vm, void *reserved) { return JNI_VERSION_1_2;}
www.hazelcast.com@noctarius2k
extern C { JNIEXPORT int JNICALL Java_ProcessIdentifier_getProcessId(JNIEnv *, jobject);}
JNIEXPORT int JNICALLJava_ProcessIdentifier_getProcessId(JNIEnv *env, jobject thisObject) { return getpid();}
oh, missing the Java side, stillJNIEXPORT jint JNICALLJNI_OnLoad(JavaVM *vm, void *reserved) { return JNI_VERSION_1_2;}
public class ProcessIdentifier { static { System.loadLibrary("processidentifier"); }
public native void getProcessId();}
www.hazelcast.com@noctarius2k
extern C { JNIEXPORT int JNICALL Java_ProcessIdentifier_getProcessId(JNIEnv *, jobject);}
JNIEXPORT int JNICALLJava_ProcessIdentifier_getProcessId(JNIEnv *env, jobject thisObject) { return getpid();}
oh, missing the Java side, stillJNIEXPORT jint JNICALLJNI_OnLoad(JavaVM *vm, void *reserved) { return JNI_VERSION_1_2;}
public class ProcessIdentifier { static { System.loadLibrary("processidentifier"); }
public native void getProcessId();}
Java Classname
www.hazelcast.com@noctarius2k
extern C { JNIEXPORT int JNICALL Java_ProcessIdentifier_getProcessId(JNIEnv *, jobject);}
JNIEXPORT int JNICALLJava_ProcessIdentifier_getProcessId(JNIEnv *env, jobject thisObject) { return getpid();}
oh, missing the Java side, stillJNIEXPORT jint JNICALLJNI_OnLoad(JavaVM *vm, void *reserved) { return JNI_VERSION_1_2;}
public class ProcessIdentifier { static { System.loadLibrary("processidentifier"); }
public native void getProcessId();}
Java Classname Java Methodname
www.hazelcast.com@noctarius2k
extern C { JNIEXPORT int JNICALL Java_ProcessIdentifier_getProcessId(JNIEnv *, jobject);}
JNIEXPORT int JNICALLJava_ProcessIdentifier_getProcessId(JNIEnv *env, jobject thisObject) { return getpid();}
ok, ok, now we’re done!JNIEXPORT jint JNICALLJNI_OnLoad(JavaVM *vm, void *reserved) { return JNI_VERSION_1_2;}
public class ProcessIdentifier { static { System.loadLibrary("processidentifier"); }
public native void getProcessId();}
www.hazelcast.com@noctarius2k
Wasn’t that easy?
www.hazelcast.com@noctarius2k
Wasn’t that easy?
but remember…
www.hazelcast.com@noctarius2k
Everybody struggles with JNI!
www.hazelcast.com@noctarius2k
meanwhile behind the wall…
www.hazelcast.com@noctarius2k
Java 9 to the rescue
www.hazelcast.com@noctarius2k
Java 9 to the rescue
long pid = ProcessHandle.current().getPid();
www.hazelcast.com@noctarius2k
Java 9 to the rescue
long pid = ProcessHandle.current().getPid();
convenient, eh?
www.hazelcast.com@noctarius2k
but how many can just update?
www.hazelcast.com@noctarius2k
So? JNI?
www.hazelcast.com@noctarius2k
So? JNI? - NO!
www.hazelcast.com@noctarius2k
A Song From Methods And Handles
www.hazelcast.com@noctarius2k
MethodHandlesMethodType type = MethodType.methodType(int.class);MethodHandle mh = MethodHandles.lookup() .findVirtual(ProcessIdentifier.class, "getProcessId", type);
int pid = mh.invokeExact();
www.hazelcast.com@noctarius2k
MethodHandlesMethodType type = MethodType.methodType(int.class);MethodHandle mh = MethodHandles.lookup() .findVirtual(ProcessIdentifier.class, "getProcessId", type);
int pid = mh.invokeExact();
type definition
www.hazelcast.com@noctarius2k
MethodHandlesMethodType type = MethodType.methodType(int.class);MethodHandle mh = MethodHandles.lookup() .findVirtual(ProcessIdentifier.class, "getProcessId", type);
int pid = mh.invokeExact();
returntypetype definition
www.hazelcast.com@noctarius2k
MethodHandlesMethodType type = MethodType.methodType(int.class);MethodHandle mh = MethodHandles.lookup() .findVirtual(ProcessIdentifier.class, "getProcessId", type);
int pid = mh.invokeExact();
returntypetype definition
Java Classname
www.hazelcast.com@noctarius2k
MethodHandlesMethodType type = MethodType.methodType(int.class);MethodHandle mh = MethodHandles.lookup() .findVirtual(ProcessIdentifier.class, "getProcessId", type);
int pid = mh.invokeExact();
returntypetype definition
Java Classname Java Methodname
www.hazelcast.com@noctarius2k
MethodHandlesMethodType type = MethodType.methodType(int.class);MethodHandle mh = MethodHandles.lookup() .findVirtual(ProcessIdentifier.class, "getProcessId", type);
int pid = mh.invokeExact();
returntypetype definition
Java Classname Java Methodnamecall the new callsite
www.hazelcast.com@noctarius2k
MethodHandles
So? What’s the deal? Java 7, right?
www.hazelcast.com@noctarius2k
MethodHandlesMethodType type = MethodType.methodType(int.class);MethodHandle mh = MethodHandles.lookup() .findVirtual(ProcessIdentifier.class, "getProcessId", type);
int pid = mh.invokeExact();
www.hazelcast.com@noctarius2k
MethodHandlesMethodType type = MethodType.methodType(int.class);MethodHandle mh = MethodHandles.lookup() .findVirtual(ProcessIdentifier.class, "getProcessId", type);
int pid = mh.invokeExact();
virtual call
www.hazelcast.com@noctarius2k
MethodHandlesMethodType type = MethodType.methodType(int.class);MethodHandle mh = MethodHandles.lookup() .findNative(null, "getpid", type);
int pid = mh.invokeExact();
native
www.hazelcast.com@noctarius2k
MethodHandlesMethodType type = MethodType.methodType(int.class);MethodHandle mh = MethodHandles.lookup() .findNative(null, "getpid", type);
int pid = mh.invokeExact();
native
native call
www.hazelcast.com@noctarius2k
MethodHandlesMethodType type = MethodType.methodType(int.class);MethodHandle mh = MethodHandles.lookup() .findNative(null, "getpid", type);
int pid = mh.invokeExact();
native
native call null = kernel callotherwise lib name
www.hazelcast.com@noctarius2k
Easier than takingthe Iron Throne!
www.hazelcast.com@noctarius2k
The Mad King
www.hazelcast.com@noctarius2k
Pointer with sun.misc.Unsafe
Unsafe unsafe = getUnsafeWithMagic();long ptr = unsafe.allocateMemory(20);byte val = unsafe.getByte(ptr + 5);
www.hazelcast.com@noctarius2k
Pointer with sun.misc.Unsafe
Unsafe unsafe = getUnsafeWithMagic();long ptr = unsafe.allocateMemory(20);byte val = unsafe.getByte(ptr + 5);
retrieve sun.misc.Unsafe instance
www.hazelcast.com@noctarius2k
Pointer with sun.misc.Unsafe
Unsafe unsafe = getUnsafeWithMagic();long ptr = unsafe.allocateMemory(20);byte val = unsafe.getByte(ptr + 5);
retrieve sun.misc.Unsafe instance
allocate 20 bytes
www.hazelcast.com@noctarius2k
Pointer with sun.misc.Unsafe
Unsafe unsafe = getUnsafeWithMagic();long ptr = unsafe.allocateMemory(20);byte val = unsafe.getByte(ptr + 5);
retrieve sun.misc.Unsafe instance
allocate 20 bytesget byte at ptr+5
www.hazelcast.com@noctarius2k
So I die, for using Unsafe?
www.hazelcast.com@noctarius2k
Who needs Unsafe anywaysLayoutType<Byte> layout = NativeLibrary.createLayout(byte.class);
try (Scope scope = new NativeScope()) { Pointer<Byte> p = scope.allocate(layout, 20); Reference<Byte> ref = p.offset(5).deref(); byte val = ref.get();}
www.hazelcast.com@noctarius2k
Who needs Unsafe anywaysLayoutType<Byte> layout = NativeLibrary.createLayout(byte.class);
try (Scope scope = new NativeScope()) { Pointer<Byte> p = scope.allocate(layout, 20); Reference<Byte> ref = p.offset(5).deref(); byte val = ref.get();}
byte-arraylayout
www.hazelcast.com@noctarius2k
Who needs Unsafe anywaysLayoutType<Byte> layout = NativeLibrary.createLayout(byte.class);
try (Scope scope = new NativeScope()) { Pointer<Byte> p = scope.allocate(layout, 20); Reference<Byte> ref = p.offset(5).deref(); byte val = ref.get();}
byte-arraylayout
create ascope
www.hazelcast.com@noctarius2k
Who needs Unsafe anywaysLayoutType<Byte> layout = NativeLibrary.createLayout(byte.class);
try (Scope scope = new NativeScope()) { Pointer<Byte> p = scope.allocate(layout, 20); Reference<Byte> ref = p.offset(5).deref(); byte val = ref.get();}
byte-arraylayout
create ascope
allocate 20 bytes
www.hazelcast.com@noctarius2k
Who needs Unsafe anywaysLayoutType<Byte> layout = NativeLibrary.createLayout(byte.class);
try (Scope scope = new NativeScope()) { Pointer<Byte> p = scope.allocate(layout, 20); Reference<Byte> ref = p.offset(5).deref(); byte val = ref.get();}
byte-arraylayout
create ascope
allocate 20 bytesget byte at ptr+5
www.hazelcast.com@noctarius2k
Who needs Unsafe anyways
www.hazelcast.com@noctarius2k
Who needs Unsafe anyways
www.hazelcast.com@noctarius2k
A REAL NULL POINTER! THANK YOU JAVA!
Who needs Unsafe anyways
www.hazelcast.com@noctarius2k
About Structs and other Creatures
www.hazelcast.com@noctarius2k
Struct in Java? No, Layout!
typedef struct { int32_t val; Node next;} Node;
www.hazelcast.com@noctarius2k
Same LinkedList Node in Java
@LayoutDesc({"x:jint:4", "y:Node:8"})public interface Node extends Layout { // …}
www.hazelcast.com@noctarius2k
@LayoutDesc({"x:jint:4", "y:Node:8"})public interface Node extends Layout { interface EffectiveAddress { IntPointer val(); Pointer<Node> next(); } // …}
Same LinkedList Node in Java
www.hazelcast.com@noctarius2k
@LayoutDesc({"x:jint:4", "y:Node:8"})public interface Node extends Layout { Node.EffectiveAddress EA(); long sizeof(); int val(); // …}
Same LinkedList Node in Java
www.hazelcast.com@noctarius2k
@LayoutDesc({"x:jint:4", "y:Node:8"})public interface Node extends Layout { Node next(); void val(int val); void next(Node next); String toString();}
Same LinkedList Node in Java
www.hazelcast.com@noctarius2k
Scope scope = new NativeScope();Pointer<Node> ptr = scope.allocate(Node.class);Node node = ptr.getLayout();int val = node.val();Node next = node.next();
Creating layouted Objects
www.hazelcast.com@noctarius2k
I slayed the Mad King
www.hazelcast.com@noctarius2k
Value Isn’t A Pit. Value Is A Ladder.
www.hazelcast.com@noctarius2k
Value Types
value class Point { int x; int y;}
www.hazelcast.com@noctarius2k
Value Types
Point point = __make Point(1, 2);int x = point.x;int y = point.y;
www.hazelcast.com@noctarius2k
Yet another layout?
www.hazelcast.com@noctarius2k
class Point {}Point[] points = …
Arrays of Points
www.hazelcast.com@noctarius2k
value class Point {}Point[] points = …
Arrays of Points
www.hazelcast.com@noctarius2k
I’m feeling so Assembler today
www.hazelcast.com@noctarius2k
Coding a Vector-Function in JavaMethodType type = MethodType.methodType( Float.class, Float.class, Float.class);
MethodHandle m256_vadds = CodeSnippets .make(..., type, …);
m256_vadds.invokeExact(out, in1, in2);
low-level
www.hazelcast.com@noctarius2k
Coding a Vector-Function in Javahigh-level
interface Vector<E, S extends Shape<Vector?, S>> { Vector<E, S> add (Vector<E, S> other); Vector<E, S> mul (Vector<E, S> other); Vector<E, S> and (Vector<E, S> other); // ... more operations}
www.hazelcast.com@noctarius2k
Coding a Vector-Function in Javahigh-level
void addVector(float[] left, float[] right, float[] res, int length) { // …}
www.hazelcast.com@noctarius2k
Coding a Vector-Function in Javahigh-level
void addVector(float[] left, float[] right, float[] res, int length) { FloatVector<S256Bit> l = float256FromArray(left, length); FloatVector<S256Bit> r = float256FromArray(right, length); // …}
www.hazelcast.com@noctarius2k
Coding a Vector-Function in Javahigh-level
void addVector(float[] left, float[] right, float[] res, int length) { // … FloatVector<S256Bit> lr = l.add(r); lr.intoArray(res, length);}
www.hazelcast.com@noctarius2k
Razersharp tooling
www.hazelcast.com@noctarius2k
So what do we expect?
www.hazelcast.com@noctarius2k
Peace with the Dragons
www.hazelcast.com@noctarius2k
Peace with the DragonsC / C++
www.hazelcast.com@noctarius2k
Painless communication…
www.hazelcast.com@noctarius2k
Painless communication…
…between native and Java code
www.hazelcast.com@noctarius2k
More fun…
www.hazelcast.com@noctarius2k
More fun…
… and faster code …
www.hazelcast.com@noctarius2k
More fun…
…without JNI
… and faster code …
www.hazelcast.com@noctarius2k
Thank You &George R.R. Martin
www.hazelcast.com@noctarius2k
More information:• http://openjdk.java.net/projects/valhalla/ • http://openjdk.java.net/projects/panama/ • http://cr.openjdk.java.net/~jrose/values/values-0.html • http://blog.codefx.org/java/dev/the-road-to-valhalla/ • http://openjdk.java.net/jeps/191 • https://www.youtube.com/watch?v=JR1zI5gLhRM • https://github.com/J9Java/panama-layout-prototype • https://developer.ibm.com/open/openprojects/project-panama-layout-prototype/ • https://www.youtube.com/watch?v=Tc9vs_HFHVo • https://www.youtube.com/watch?v=Z2XgO1H6xPM
Thank You!
www.hazelcast.com@noctarius2k
Thank You!Any Questions?
@noctarius2k http://www.sourceprojects.org
http://github.com/noctarius
@hazelcast http://www.hazelcast.com http://www.hazelcast.org
http://github.com/hazelcast
www.hazelcast.com@noctarius2k
Germanspeaking?
JVM related talk on Slack
Get your own invite at:https://slackin-jvm-german.herokuapp.com