Slide 1

Slide 1 text

В нативный код из уютного мира Java Путешествие Туда и Обратно Иван Углянский Excelsior@Huawei

Slide 2

Slide 2 text

Иван Углянский 2 JVM engineer at Excelsior@Huawei [email protected] @dbg_nsk JUGNsk co-lead

Slide 3

Slide 3 text

Какой еще нативный код? 3

Slide 4

Slide 4 text

Какой еще нативный код? 4 public class JavaToNative { static native void goNative(); static native void goThere(Callback andBackAgain); }

Slide 5

Slide 5 text

Какой еще нативный код? 5 public class JavaToNative { static native void goNative(); static native void goThere(Callback andBackAgain); }

Slide 6

Slide 6 text

Какой еще нативный код? 6 public class JavaToNative { static native void goNative(); static native void goThere(Callback andBackAgain); } Java C/C++/... goNative

Slide 7

Slide 7 text

Какой еще нативный код? 7 public class JavaToNative { static native void goNative(); static native void goThere(Callback andBackAgain); } Java goThere andBackAgain C/C++/...

Slide 8

Slide 8 text

Но зачем нам нативы? 8

Slide 9

Slide 9 text

Но зачем нам нативы? 9 Java - managed язык

Slide 10

Slide 10 text

Но зачем нам нативы? 10 Java - managed язык ○ автоматическое управление памятью

Slide 11

Slide 11 text

Но зачем нам нативы? 11 Java - managed язык ○ автоматическое управление памятью ○ безопасные операции

Slide 12

Slide 12 text

Но зачем нам нативы? 12 Java - managed язык ○ автоматическое управление памятью ○ безопасные операции Java - это...

Slide 13

Slide 13 text

13

Slide 14

Slide 14 text

Но зачем нам нативы? 14 Java - managed язык ○ автоматическое управление памятью ○ безопасные операции А вот нативный код - это...

Slide 15

Slide 15 text

Причины звать нативный код из Java 15

Slide 16

Slide 16 text

Но знаете, как это бывает... 16

Slide 17

Slide 17 text

Причины звать нативный код из Java 17 1. Есть отличная библиотека! (Но она на С/C++)

Slide 18

Slide 18 text

Причины звать нативный код из Java 18 1. Есть отличная библиотека! (Но она на С/C++) OpenGL, DirectX, Tensorflow, Cuda, OpenCL, OpenSSl, Vulkan, Криптография, ...

Slide 19

Slide 19 text

Причины звать нативный код из Java 19 1. Есть отличная библиотека! (Но она на С/C++) 2. Да мне всего лишь один метод из WinAPI позвать!

Slide 20

Slide 20 text

Причины звать нативный код из Java 20 1. Есть отличная библиотека! (Но она на С/C++) 2. Да мне всего лишь один метод из WinAPI позвать! 3. Напишу один модуль на C++, все как разгонится!

Slide 21

Slide 21 text

21

Slide 22

Slide 22 text

22 A fatal error has been detected by the Java Runtime Environment: # # SIGSEGV (0xb) at pc=0x00007f542922359f, pid=25670, tid=0x00007f5444efa700 # # JRE version: Java(TM) SE Runtime Environment (8.0_151-b12) (build 1.8.0_151-b12) # Java VM: Java HotSpot(TM) 64-Bit Server VM (25.151-b12 mixed mode linux-amd64 compressed oops) # Problematic frame: # C [libavutil.so.56+0x1159f] av_strstart+0x1f

Slide 23

Slide 23 text

23 A fatal error has been detected by the Java Runtime Environment: # # SIGSEGV (0xb) at pc=0x00007f542922359f, pid=25670, tid=0x00007f5444efa700 # # JRE version: Java(TM) SE Runtime Environment (8.0_151-b12) (build 1.8.0_151-b12) # Java VM: Java HotSpot(TM) 64-Bit Server VM (25.151-b12 mixed mode linux-amd64 compressed oops) # Problematic frame: # C [libavutil.so.56+0x1159f] av_strstart+0x1f # EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x0000000180005b00, pid=13432, tid=13952 # # JRE version: Java(TM) SE Runtime Environment (12.0.2+10) (build 12.0.2+10) # Java VM: Java HotSpot(TM) 64-Bit Server VM (12.0.2+10, mixed mode, sharing, tiered, compressed oops, g1 gc, windows-amd64) # Problematic frame: # C [rxtxSerial.dll+0x5b00]

Slide 24

Slide 24 text

24 A fatal error has been detected by the Java Runtime Environment: # # SIGSEGV (0xb) at pc=0x00007f542922359f, pid=25670, tid=0x00007f5444efa700 # # JRE version: Java(TM) SE Runtime Environment (8.0_151-b12) (build 1.8.0_151-b12) # Java VM: Java HotSpot(TM) 64-Bit Server VM (25.151-b12 mixed mode linux-amd64 compressed oops) # Problematic frame: # C [libavutil.so.56+0x1159f] av_strstart+0x1f # EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x0000000180005b00, pid=13432, tid=13952 # # JRE version: Java(TM) SE Runtime Environment (12.0.2+10) (build 12.0.2+10) # Java VM: Java HotSpot(TM) 64-Bit Server VM (12.0.2+10, mixed mode, sharing, tiered, compressed oops, g1 gc, windows-amd64) # Problematic frame: # C [rxtxSerial.dll+0x5b00] # SIGSEGV (0xb) at pc=0x00007f098dac2618, pid=1720, tid=0x00007f0963f7a700 # # JRE version: OpenJDK Runtime Environment (8.0_212-b03) (build 1.8.0_212-8u212-b03-0ubuntu1.18.04.1-b03) # Java VM: OpenJDK 64-Bit Server VM (25.212-b03 mixed mode linux-amd64 compressed oops) # Problematic frame: # C [libopencv_core.so.3.2+0x132618] cv::_InputArray::size(int) const+0x1d8

Slide 25

Slide 25 text

25 A fatal error has been detected by the Java Runtime Environment: # # SIGSEGV (0xb) at pc=0x00007f542922359f, pid=25670, tid=0x00007f5444efa700 # # JRE version: Java(TM) SE Runtime Environment (8.0_151-b12) (build 1.8.0_151-b12) # Java VM: Java HotSpot(TM) 64-Bit Server VM (25.151-b12 mixed mode linux-amd64 compressed oops) # Problematic frame: # C [libavutil.so.56+0x1159f] av_strstart+0x1f # EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x0000000180005b00, pid=13432, tid=13952 # # JRE version: Java(TM) SE Runtime Environment (12.0.2+10) (build 12.0.2+10) # Java VM: Java HotSpot(TM) 64-Bit Server VM (12.0.2+10, mixed mode, sharing, tiered, compressed oops, g1 gc, windows-amd64) # Problematic frame: # C [rxtxSerial.dll+0x5b00] # SIGSEGV (0xb) at pc=0x00007f098dac2618, pid=1720, tid=0x00007f0963f7a700 # # JRE version: OpenJDK Runtime Environment (8.0_212-b03) (build 1.8.0_212-8u212-b03-0ubuntu1.18.04.1-b03) # Java VM: OpenJDK 64-Bit Server VM (25.212-b03 mixed mode linux-amd64 compressed oops) # Problematic frame: # C [libopencv_core.so.3.2+0x132618] cv::_InputArray::size(int) const+0x1d8

Slide 26

Slide 26 text

Будем разбираться 26

Slide 27

Slide 27 text

Будем разбираться 27 1. Почему так много проблем с нативами?

Slide 28

Slide 28 text

Будем разбираться 28 1. Почему так много проблем с нативами? 2. Как пройти в Мордор и не получить SIGSEGV?

Slide 29

Slide 29 text

Как позвать натив? 29

Slide 30

Slide 30 text

Как позвать натив? 30 Где взять нативы?

Slide 31

Slide 31 text

Как позвать натив? 31 Где взять нативы? Как работать с Java из натива?

Slide 32

Slide 32 text

Как позвать натив? 32 Как себя должен вести GC? Где взять нативы? Как работать с Java из натива?

Slide 33

Slide 33 text

Немного истории 33

Slide 34

Slide 34 text

1. JDK 1.0 NMI — Native Method Invocation (Sun JVM) 2. Raw Native Interface (RNI) in Microsoft J++ and J/Direct 3. Netscape’s JRI (Java Runtime Interface) 4. ... История до нашей эры 34

Slide 35

Slide 35 text

Наша эра 35 JNI - Java Native Interface

Slide 36

Slide 36 text

Наша эра 36 JNI - Java Native Interface ✓ Единый интерфейс, чтобы править всеми!

Slide 37

Slide 37 text

Наша эра 37 JNI - Java Native Interface ✓ Единый интерфейс, чтобы править всеми! ✓ Детали реализации скрыты ⇒ JVM нейтрален, GC нейтрален

Slide 38

Slide 38 text

Как это выглядит со стороны Java? 38

Slide 39

Slide 39 text

Как это выглядит со стороны Java? 39 public class JavaToNative { static native void goNative(); static native void goThere(Callback andBackAgain); public static void main(String[] args) { System.loadLibrary("NativeLib"); goThere(new Callback("Eagles")); } }

Slide 40

Slide 40 text

Как это выглядит со стороны Java? 40 public class JavaToNative { static native void goNative(); static native void goThere(Callback andBackAgain); public static void main(String[] args) { System.loadLibrary("NativeLib"); goThere(new Callback("Eagles")); } }

Slide 41

Slide 41 text

Как это выглядит со стороны Java? 41 public class JavaToNative { static native void goNative(); static native void goThere(Callback andBackAgain); public static void main(String[] args) { System.loadLibrary("NativeLib"); goThere(new Callback("Eagles")); } }

Slide 42

Slide 42 text

Как это выглядит со стороны Java? 42 public class JavaToNative { static native void goNative(Object obj); static native void goThere(Callback andBackAgain); public static void main(String[] args) { System.loadLibrary("NativeLib"); goThere(new Callback("Eagles")); } } class Callback { private final String transport; public Callback(String transport) { this.transport = transport; } public void call() { System.out.println("Ok, we are in Shire again! Returned by " + transport); } }

Slide 43

Slide 43 text

Как это выглядит со стороны С? 43

Slide 44

Slide 44 text

Как это выглядит со стороны С? 44 public class JavaToNative { static native void goThere(Callback andBackAgain); }

Slide 45

Slide 45 text

Как это выглядит со стороны С? 45 public class JavaToNative { static native void goThere(Callback andBackAgain); } javac JavaToNative.java -h .

Slide 46

Slide 46 text

Как это выглядит со стороны С? 46 public class JavaToNative { static native void goThere(Callback andBackAgain); } JNIEXPORT void JNICALL Java_JavaToNative_goThere (JNIEnv *, jclass, jobject); javac JavaToNative.java -h . JavaToNative.h

Slide 47

Slide 47 text

Как это выглядит со стороны С? 47 public class JavaToNative { static native void goThere(Callback andBackAgain); } JNIEXPORT void JNICALL Java_JavaToNative_goThere (JNIEnv *, jclass, jobject); javac JavaToNative.java -h . JavaToNative.h

Slide 48

Slide 48 text

Как это выглядит со стороны С? 48 boolean jboolean unsigned 8 bits byte jbyte signed 8 bits char jchar unsigned 16 bits short jshort signed 16 bits int jint signed 32 bits long jlong signed 64 bits float jfloat 32 bits double jdouble 64 bits void void N/A Примитивные

Slide 49

Slide 49 text

Как это выглядит со стороны С? 49 boolean jboolean unsigned 8 bits byte jbyte signed 8 bits char jchar unsigned 16 bits short jshort signed 16 bits int jint signed 32 bits long jlong signed 64 bits float jfloat 32 bits double jdouble 64 bits void void N/A Примитивные Ссылочные jobject jclass jstring jthrowable jarray jobjectArray jbooleanArray jcharArray ...

Slide 50

Slide 50 text

Как это выглядит со стороны С? 50 public class JavaToNative { static native void goThere(Callback andBackAgain); } JNIEXPORT void JNICALL Java_JavaToNative_goThere (JNIEnv *, jclass, jobject); javac JavaToNative.java -h . JavaToNative.h

Slide 51

Slide 51 text

Как это выглядит со стороны С? 51 JNIEnv

Slide 52

Slide 52 text

Как это выглядит со стороны С? 52 JNIEnv ✓ Указатель на JNINativeInterface (214 функций)

Slide 53

Slide 53 text

Как это выглядит со стороны С? 53 JNIEnv ✓ Указатель на JNINativeInterface (214 функций) GetVersion, DefineClass, FindClass, FromReflectedMethod, FromReflectedField, ToReflectedMethod, GetSuperclass, IsAssignableFrom, ToReflectedField, Throw, ThrowNew, ExceptionOccurred, ExceptionDescribe, ExceptionClear, FatalError, PushLocalFrame, PopLocalFrame, NewGlobalRef, DeleteGlobalRef, DeleteLocalRef, IsSameObject, NewLocalRef, EnsureLocalCapacity, AllocObject, NewObject, NewObjectV, NewObjectA, GetObjectClass, IsInstanceOf, GetMethodID, CallObjectMethod, CallObjectMethodV, CallObjectMethodA, CallBooleanMethod, CallBooleanMethodV, CallBooleanMethodA, CallByteMethod, CallByteMethodV, CallByteMethodA, CallCharMethod, CallCharMethodV, CallCharMethodA, CallShortMethod, CallShortMethodV, CallShortMethodA, CallIntMethod, CallIntMethodV, CallIntMethodA, CallLongMethod, CallLongMethodV, CallLongMethodA, CallFloatMethod, CallFloatMethodV, CallFloatMethodA, CallDoubleMethod, CallDoubleMethodV, CallDoubleMethodA, CallVoidMethod, CallVoidMethodV, CallVoidMethodA, CallNonvirtualObjectMethod, CallNonvirtualObjectMethodV, CallNonvirtualObjectMethodA, CallNonvirtualBooleanMethod, CallNonvirtualBooleanMethodV, CallNonvirtualBooleanMethodA, CallNonvirtualByteMethod, CallNonvirtualByteMethodV, CallNonvirtualByteMethodA, CallNonvirtualCharMethod, CallNonvirtualCharMethodV, CallNonvirtualCharMethodA, CallNonvirtualShortMethod, CallNonvirtualShortMethodV, CallNonvirtualShortMethodA, CallNonvirtualIntMethod, CallNonvirtualIntMethodV, CallNonvirtualIntMethodA, CallNonvirtualLongMethod, CallNonvirtualLongMethodV, CallNonvirtualLongMethodA, CallNonvirtualFloatMethod, CallNonvirtualFloatMethodV, CallNonvirtualFloatMethodA, CallNonvirtualDoubleMethod, CallNonvirtualDoubleMethodV, CallNonvirtualDoubleMethodA, CallNonvirtualVoidMethod, CallNonvirtualVoidMethodV, CallNonvirtualVoidMethodA, GetFieldID, GetObjectField, GetBooleanField, GetByteField, GetCharField, GetShortField, GetIntField, GetLongField, GetFloatField, GetDoubleField, SetObjectField, SetBooleanField, SetByteField, SetCharField, SetShortField, SetIntField, SetLongField, SetFloatField, SetDoubleField, GetStaticMethodID, CallStaticObjectMethod, CallStaticObjectMethodV, CallStaticObjectMethodA, CallStaticBooleanMethod, CallStaticBooleanMethodV, CallStaticBooleanMethodA, CallStaticByteMethod, CallStaticByteMethodV, CallStaticByteMethodA, CallStaticCharMethod, CallStaticCharMethodV, CallStaticCharMethodA, CallStaticShortMethod, CallStaticShortMethodV, CallStaticShortMethodA, CallStaticIntMethod, CallStaticIntMethodV, CallStaticIntMethodA, CallStaticLongMethod, CallStaticLongMethodV, CallStaticLongMethodA, CallStaticFloatMethod, CallStaticFloatMethodV, CallStaticFloatMethodA, CallStaticDoubleMethod, CallStaticDoubleMethodV, CallStaticDoubleMethodA, CallStaticVoidMethod, CallStaticVoidMethodV, CallStaticVoidMethodA, GetStaticFieldID, GetStaticObjectField, GetStaticBooleanField, ...

Slide 54

Slide 54 text

Как это выглядит со стороны С? 54 JNIEnv ✓ Указатель на JNINativeInterface (214 функций) NewObject, GetObjectClass, GetObjectField, SetObjectField, GetField, SetField, CallObjectMethod, CallStaticObjectMethod CallMethod, CallStaticMethod Throw, ThrowNew, Очень похоже на Reflection! «мета»-программирование на Java

Slide 55

Slide 55 text

Как это выглядит со стороны С? 55 JNIEnv ✓ Указатель на JNINativeInterface (214 функций) ✓ Только через них можно взаимодействовать с Java docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/functions.html

Slide 56

Slide 56 text

Как это выглядит со стороны С? 56 /* * Class: JavaToNative * Method: goThere * Signature: (LCallback;)V */ JNIEXPORT void JNICALL Java_JavaToNative_goThere(JNIEnv * env, jclass klass, jobject andBackAgain) { } JavaToNative.c

Slide 57

Slide 57 text

Как это выглядит со стороны С? 57 /* * Class: JavaToNative * Method: goThere * Signature: (LCallback;)V */ JNIEXPORT void JNICALL Java_JavaToNative_goThere(JNIEnv * env, jclass klass, jobject andBackAgain) { printf("Ok, we are in Mordor now!\n"); } JavaToNative.c

Slide 58

Slide 58 text

Как это выглядит со стороны С? 58 /* * Class: JavaToNative * Method: goThere * Signature: (LCallback;)V */ JNIEXPORT void JNICALL Java_JavaToNative_goThere(JNIEnv * env, jclass klass, jobject andBackAgain) { printf("Ok, we are in Mordor now!\n"); jclass cls = (*env)->GetObjectClass(env, andBackAgain); jmethodID method = (*env)->GetMethodID(env, cls, "call", "()V"); } JavaToNative.c

Slide 59

Slide 59 text

Как это выглядит со стороны С? 59 /* * Class: JavaToNative * Method: goThere * Signature: (LCallback;)V */ JNIEXPORT void JNICALL Java_JavaToNative_goThere(JNIEnv * env, jclass klass, jobject andBackAgain) { printf("Ok, we are in Mordor now!\n"); jclass cls = (*env)->GetObjectClass(env, andBackAgain); jmethodID method = (*env)->GetMethodID(env, cls, "call", "()V"); (*env)->CallVoidMethod(env, andBackAgain, method); } JavaToNative.c

Slide 60

Slide 60 text

Собираем! 60

Slide 61

Slide 61 text

Собираем! 61 gcc.exe -Wall -D_JNI_IMPLEMENTATION_ -Wl,--kill-at -I %JAVA_HOME%/include -I %JAVA_HOME%/include/win32 -I. -L %JAVA_HOME%/jre/lib -shared JavaToNative.c -o lib/NativeLib.dll

Slide 62

Slide 62 text

Собираем! 62 gcc.exe -Wall -D_JNI_IMPLEMENTATION_ -Wl,--kill-at -I %JAVA_HOME%/include -I %JAVA_HOME%/include/win32 -I. -L %JAVA_HOME%/jre/lib -shared JavaToNative.c -o lib/NativeLib.dll Nokee plugins ✓ Кроссплатформенное решение ✓ Удобное использование через Gradle ✓ nokee.dev

Slide 63

Slide 63 text

Собираем и запускаем! 63 gcc.exe -Wall -D_JNI_IMPLEMENTATION_ -Wl,--kill-at -I %JAVA_HOME%/include -I %JAVA_HOME%/include/win32 -I. -L %JAVA_HOME%/jre/lib -shared JavaToNative.c -o lib/NativeLib.dll public class JavaToNative { static native void goThere(Callback andBackAgain); public static void main(String[] args) { System.loadLibrary("NativeLib"); goThere(new Callback("Eagles")); } }

Slide 64

Slide 64 text

Собираем и запускаем! 64 gcc.exe -Wall -D_JNI_IMPLEMENTATION_ -Wl,--kill-at -I %JAVA_HOME%/include -I %JAVA_HOME%/include/win32 -I. -L %JAVA_HOME%/jre/lib -shared JavaToNative.c -o lib/NativeLib.dll public class JavaToNative { static native void goThere(Callback andBackAgain); public static void main(String[] args) { System.loadLibrary("NativeLib"); goThere(new Callback("Eagles")); } } $ java -Djava.library.path=./lib JavaToNative Ok, we are in Mordor now! Ok, we are in Shire again! Returned by Eagles

Slide 65

Slide 65 text

Что может пойти не так? 65

Slide 66

Slide 66 text

Что может пойти не так? 66 ✓ Статическая типовая информация утеряна. Добро пожаловать в JavaScript!

Slide 67

Slide 67 text

67 /* * Class: JavaToNative * Method: goThere * Signature: (LCallback;)V */ JNIEXPORT void JNICALL Java_JavaToNative_goThere(JNIEnv * env, jclass klass, jobject andBackAgain) { printf("Ok, we are in Mordor now!\n"); jclass cls = (*env)->GetObjectClass(env, andBackAgain); jmethodID method = (*env)->GetMethodID(env, cls, "call", "()V"); (*env)->CallVoidMethod(env, andBackAgain, method); }

Slide 68

Slide 68 text

68 /* * Class: JavaToNative * Method: goThere * Signature: (LCallback;Ljava/lang/Object)V */ JNIEXPORT void JNICALL Java_JavaToNative_goThere(JNIEnv * env, jclass klass, jobject andBackAgain, jobject luggage) { printf("Ok, we are in Mordor now!\n"); jclass cls = (*env)->GetObjectClass(env, andBackAgain); jmethodID method = (*env)->GetMethodID(env, cls, "call", "()V"); (*env)->CallVoidMethod(env, luggage, method); } java -Djava.library.path=./lib JavaToNative

Slide 69

Slide 69 text

69 /* * Class: JavaToNative * Method: goThere * Signature: (LCallback;Ljava/lang/Object)V */ JNIEXPORT void JNICALL Java_JavaToNative_goThere(JNIEnv * env, jclass klass, jobject andBackAgain, jobject luggage) { printf("Ok, we are in Mordor now!\n"); jclass cls = (*env)->GetObjectClass(env, andBackAgain); jmethodID method = (*env)->GetMethodID(env, cls, "call", "()V"); (*env)->CallVoidMethod(env, luggage, method); } java -Djava.library.path=./lib JavaToNative Ok, we are in Mordor now! # A fatal error has been detected by the Java Runtime Environment: # # EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x00007ffb8add70e1, pid=14100, tid=12564 # # JRE version: OpenJDK Runtime Environment AdoptOpenJDK (14.0.1+7) (build 14.0.1+7) # Java VM: OpenJDK 64-Bit Server VM AdoptOpenJDK (14.0.1+7, mixed mode, sharing, tiered, compressed oops , g1 gc, windows-amd64) # Problematic frame: # V [jvm.dll+0x3970e1]

Slide 70

Slide 70 text

Что может пойти не так? 70 ✓ Статическая типовая информация утеряна. Добро пожаловать в JavaScript! ✓ Вызов правильных JNI функций - ваша ответственность

Slide 71

Slide 71 text

Что может пойти не так? 71 ✓ Статическая типовая информация утеряна. Добро пожаловать в JavaScript! ✓ Вызов правильных JNI функций - ваша ответственность ✓ Исключения из Java не пробрасываются (см. ExceptionOccurred, ExceptionClear)

Slide 72

Slide 72 text

72 -Xcheck:jni

Slide 73

Slide 73 text

73 /* * Class: JavaToNative * Method: goThere * Signature: (LCallback;Ljava/lang/Object)V */ JNIEXPORT void JNICALL Java_JavaToNative_goThere(JNIEnv * env, jclass klass, jobject andBackAgain, jobject luggage) { printf("Ok, we are in Mordor now!\n"); jclass cls = (*env)->GetObjectClass(env, andBackAgain); jmethodID method = (*env)->GetMethodID(env, cls, "call", "()V"); (*env)->CallVoidMethod(env, luggage, method); } java -Djava.library.path=./lib JavaToNative

Slide 74

Slide 74 text

74 /* * Class: JavaToNative * Method: goThere * Signature: (LCallback;Ljava/lang/Object)V */ JNIEXPORT void JNICALL Java_JavaToNative_goThere(JNIEnv * env, jclass klass, jobject andBackAgain, jobject luggage) { printf("Ok, we are in Mordor now!\n"); jclass cls = (*env)->GetObjectClass(env, andBackAgain); jmethodID method = (*env)->GetMethodID(env, cls, "call", "()V"); (*env)->CallVoidMethod(env, luggage, method); } java -Xcheck:jni -Djava.library.path=./lib JavaToNative

Slide 75

Slide 75 text

75 java -Xcheck:jni -Djava.library.path=./lib JavaToNative Ok, we are in Mordor now! FATAL ERROR in native method: Wrong object class or methodID passed to JNI call at JavaToNative.goThere(Native Method) at JavaToNative.main(JavaToNative.java:9)

Slide 76

Slide 76 text

Что может пойти не так? 76 ✓ Статическая типовая информация утеряна. Добро пожаловать в JavaScript! ✓ Вызов правильных JNI функций - ваша ответственность ✓ Исключения из Java не пробрасываются ✓ -Xcheck:jni значительно улучшает диагностику простых случаев (но это стоит дорого)

Slide 77

Slide 77 text

Как позвать натив? 77 Как себя должен вести GC? Где взять нативы? Как работать с Java из натива?

Slide 78

Slide 78 text

GC в Java коде 78 ○ safe-points, в которых "припарковываются" потоки

Slide 79

Slide 79 text

79 ○ safe-points, в которых "припарковываются" потоки ○ GC ждет, пока потоки припаркуются Threads in Java code GC request GC в Java коде

Slide 80

Slide 80 text

GC в Java коде 80 ○ safe-points, в которых "припарковываются" потоки ○ GC ждет, пока потоки припаркуются Threads in Java code GC request

Slide 81

Slide 81 text

GC в Java коде 81 ○ safe-points, в которых "припарковываются" потоки ○ GC ждет, пока потоки припаркуются Threads in Java code GC Threads GC request

Slide 82

Slide 82 text

GC в нативном коде 82 ○ какие еще safe-points? ○ натив продолжает работать

Slide 83

Slide 83 text

83 Threads in Java code GC Threads GC request GC в нативном коде ○ какие еще safe-points? ○ натив продолжает работать

Slide 84

Slide 84 text

84 GC в нативном коде ○ какие еще safe-points? ○ натив продолжает работать Threads in Java code GC Threads GC request Threads in native

Slide 85

Slide 85 text

85 ○ какие еще safe-points? ○ натив продолжает работать ○ на входе и выходе из натива синхронизация с GC Threads in Java code GC Threads GC request Threads in native GC в нативном коде

Slide 86

Slide 86 text

86 Нельзя трогать Java объекты в нативе во время GC!

Slide 87

Slide 87 text

87 public class JavaToNative { static native void goThere(Callback andBackAgain); } JNIEXPORT void JNICALL Java_JavaToNative_goThere (JNIEnv *, jclass, jobject); javac JavaToNative.java -h . JavaToNative.h GC в нативном коде

Slide 88

Slide 88 text

88 jobject и компания - специальные хендлы, для которых: 1. JVM поддерживает связь с реальными Java объектами j.l.Object jobject Native Heap Java Heap GC в нативном коде

Slide 89

Slide 89 text

89 jobject и компания - специальные хендлы, для которых: 1. JVM поддерживает связь с реальными Java объектами j.l.Object jobject Native Heap Java Heap GC в нативном коде

Slide 90

Slide 90 text

90 jobject и компания - специальные хендлы, для которых: 1. JVM поддерживает связь с реальными Java объектами 2. Доступ к реальным Java объектам (через JNI) синхронизирован с GC j.l.Object jobject Native Heap Java Heap GC в нативном коде

Slide 91

Slide 91 text

91 jobject и компания - специальные хендлы, для которых: 1. JVM поддерживает связь с реальными Java объектами 2. Доступ к реальным Java объектам (через JNI) синхронизирован с GC 3. Содержимое считается GC-roots! j.l.Object jobject Native Heap Java Heap GC в нативном коде

Slide 92

Slide 92 text

92 Garbage Collector jobject jobject jobject

Slide 93

Slide 93 text

Подводные камни (GC + Natives) 93 ✓ Для хендлов реализована альтернативная система управления памятью

Slide 94

Slide 94 text

Подводные камни (GC + Natives) 94 ✓ Для хендлов реализована альтернативная система управления памятью Типы хендлов (в коде все выглядит, как jobject & Co):

Slide 95

Slide 95 text

Подводные камни (GC + Natives) 95 ✓ Для хендлов реализована альтернативная система управления памятью Типы хендлов (в коде все выглядит, как jobject & Co): 1. Local Reference живут не дольше одного нативного вызова

Slide 96

Slide 96 text

Подводные камни (GC + Natives) 96 ✓ Для хендлов реализована альтернативная система управления памятью Типы хендлов (в коде все выглядит, как jobject & Co): 1. Local Reference 2. Global Reference 3. Weak Global Reference живут не дольше одного нативного вызова живут, пока их явно не освободят живут, пока их явно не освободят, но GC может собрать Java объект

Slide 97

Slide 97 text

Подводные камни (GC + Natives) 97 ✓ Особая система управления памятью (в которой легко получить memory leak/dangling pointer)

Slide 98

Slide 98 text

Подводные камни (GC + Natives) 98 ✓ Особая система управления памятью (в которой легко получить memory leak/dangling pointer) ✓ Особая обработка массивов и строк: pinning vs copying

Slide 99

Slide 99 text

Подводные камни (GC + Natives) 99 ✓ Особая система управления памятью (в которой легко получить memory leak/dangling pointer) ✓ Особая обработка массивов и строк: pinning vs copying ✓ Опасные JNI методы Get*Critical (могут сильно помешать работе GC вплоть до зависания JVM) shipilev.net/jvm/anatomy-quarks/9-jni-critical-gclocker

Slide 100

Slide 100 text

Производительность нативных вызовов 100

Slide 101

Slide 101 text

Производительность нативных вызовов 101 ВСЕ ОЧЕНЬ МЕДЛЕННО

Slide 102

Slide 102 text

Производительность нативных вызовов 102 ВСЕ ОЧЕНЬ МЕДЛЕННО Измерять будем на: Intel Core i7-7700 @ 3.60 GHz; 16GB RAM; Linux Ubuntu 18.04

Slide 103

Slide 103 text

Производительность нативных вызовов 103 прямой вызов Java метода без инлайна Java Java OpenJDK 17.0.1

Slide 104

Slide 104 text

Производительность нативных вызовов 104 прямой вызов Java метода без инлайна вызов нативного метода (без параметров) из Java Java Java Java Native OpenJDK 17.0.1

Slide 105

Slide 105 text

Производительность нативных вызовов 105 прямой вызов Java метода без инлайна вызов нативного метода (без параметров) из Java Разница в 6 раз На jdk-11.0.7 Java Java Java Native OpenJDK 17.0.1

Slide 106

Slide 106 text

Производительность нативных вызовов 106 вызов нативного метода (без параметров) из Java Вызов нативного метода (без параметров) из Java, а из него вызов Java метода (без параметров) Java Native Java Java Native OpenJDK 17.0.1

Slide 107

Slide 107 text

вызов нативного метода (без параметров) из Java Вызов нативного метода (без параметров) из Java, а из него вызов Java метода (без параметров) Разница в 5 раз Производительность нативных вызовов 107 Java Native Java Java Native OpenJDK 17.0.1

Slide 108

Slide 108 text

Производительность нативных вызовов ...почему? ВСЕ ОЧЕНЬ МЕДЛЕННО

Slide 109

Slide 109 text

109 static native void goNative(); call 0x00007f4882317c70

Slide 110

Slide 110 text

110 static native void goNative(); mov DWORD PTR [rsp-0x14000],eax push rbp mov rbp,rsp sub rsp,0x40 movabs r14,0x76d381c90; mov QWORD PTR [rsp+0x30],r14 lea r14,[rsp+0x30] mov rsi,r14 movabs r10,0x7f486d4481fe mov QWORD PTR [r15+0x1c8],r10 mov QWORD PTR [r15+0x1c0],rsp cmp BYTE PTR [rip+0x154b0527],0x0 je 0x00007f486d448255 push rsi movabs rsi,0x7f486b1433f8 mov rdi,r15 test esp,0xf je 0x00007f486d44824f sub rsp,0x8 call 0x00007f4882317be0 add rsp,0x8 jmp 0x00007f486d448254 call 0x00007f4882317be0 pop rsi lea rdi,[r15+0x1e0] mov DWORD PTR [r15+0x258],0x4 call 0x00007f486073a79a vzeroupper mov DWORD PTR [r15+0x258],0x5 mov ecx,r15d shr ecx,0x4 and ecx,0xffc movabs r10,0x7f4883580000 mov DWORD PTR [r10+rcx*1],ecx cmp DWORD PTR [rip+0x154bbf5e],0x0 jne 0x00007f486d4482b2 cmp DWORD PTR [r15+0x30],0x0 je 0x00007f486d4482cb call 0x00007f4882317be0 add rsp,0x8 jmp 0x00007f486d448254 call 0x00007f4882317be0 pop rsi lea rdi,[r15+0x1e0] mov DWORD PTR [r15+0x258],0x4 call 0x00007f486073a79a mov DWORD PTR [r15+0x258],0x4 call 0x00007f486073a79a vzeroupper mov DWORD PTR [r15+0x258],0x5 mov ecx,r15d shr ecx,0x4 and ecx,0xffc movabs r10,0x7f4883580000 mov DWORD PTR [r10+rcx*1],ecx cmp DWORD PTR [rip+0x154bbf5e],0x0 jne 0x00007f486d4482b2 cmp DWORD PTR [r15+0x30],0x0 je 0x00007f486d4482cb mov rdi,r15 mov r12,rsp sub rsp,0x0 and rsp,0xfffffffffffffff0 call 0x00007f48823b84f0 mov rsp,r12 xor r12,r12 mov DWORD PTR [r15+0x258],0x8 cmp DWORD PTR [r15+0x284],0x1 je 0x00007f486d448369 cmp BYTE PTR [rip+0x154b0456],0x0 je 0x00007f486d448324 movabs rsi,0x7f486b1433f8 mov rdi,r15 test esp,0xf je 0x00007f486d44831f sub rsp,0x8 call 0x00007f4882317c70 add rsp,0x8 jmp 0x00007f486d448324 call 0x00007f4882317c70 movabs r10,0x0 mov QWORD PTR [r15+0x1c0],r10 movabs r10,0x0 mov QWORD PTR [r15+0x1c8],r10 mov rcx,QWORD PTR [r15+0x38] mov DWORD PTR [rcx+0x100],0x0 leave cmp QWORD PTR [r15+0x8],0x0 jne 0x00007f486d448364 ret jmp Stub::forward exception

Slide 111

Slide 111 text

Производительность нативных вызовов 111 ✓ State transition (Java -> Native и Native -> Java) очень дорог: 1. Синхронизация с GC 2. Завертка параметров в Local References 3. Обработка результата + exception check 4. Перепушивание параметров

Slide 112

Slide 112 text

Производительность нативных вызовов 112 ✓ State transition (Java -> Native и Native -> Java) очень дорог: 1. Синхронизация с GC 2. Завертка параметров в Local References 3. Обработка результата + exception check 4. Перепушивание параметров ✓ Никакого инлайнинга! ✓ Особенности реализации Hotspot (стабы для перехода Native -> Java)

Slide 113

Slide 113 text

1. javac -h для генерации .h файлов 2. nokee.dev для сборки 3. -Xcheck:jni для отлавливания ошибок 4. Осторожнее с JNI References и с JNI Get*Critical 5. Переход в натив (и возврат в Java) очень дорогой 113 Takeaways про JNI

Slide 114

Slide 114 text

114 JNI - хорошо, но больно

Slide 115

Slide 115 text

115 А МОЖЕТ НЕ НУЖНО ПИСАТЬ КОД НА C/C++?

Slide 116

Slide 116 text

Идея: ✓ Весь код писать на Java, а связь с нативом генерировать автоматически 116 Новейшее время

Slide 117

Slide 117 text

Идея: ✓ Весь код писать на Java, а связь с нативом генерировать автоматически Реализация: ✓ Библиотеки: JNA, JNR, JavaCPP, ... 117 Новейшее время

Slide 118

Slide 118 text

(Java Native Access) JNA net.java.dev.jna jna 5.5.0 118

Slide 119

Slide 119 text

119 JNA __declspec(dllexport) void __stdcall sayHello(const char* name) { printf("Hello %s from native!\n", name); } MyNativeLib.c

Slide 120

Slide 120 text

120 JNA __declspec(dllexport) void __stdcall sayHello(const char* name) { printf("Hello %s from native!\n", name); } MyNativeLib.c public interface MyNativeLibrary extends Library { MyNativeLibrary INSTANCE = (MyNativeLibrary) Native.load("MyNativeLib", MyNativeLibrary.class); void sayHello(String name); } TestJNA.java MyNativeLibrary.INSTANCE.sayHello("ITeaConf");

Slide 121

Slide 121 text

121 JNA __declspec(dllexport) void __stdcall sayHello(const char* name) { printf("Hello %s from native!\n", name); } MyNativeLib.c public interface MyNativeLibrary extends Library { MyNativeLibrary INSTANCE = (MyNativeLibrary) Native.load("MyNativeLib", MyNativeLibrary.class); void sayHello(String name); } TestJNA.java MyNativeLibrary.INSTANCE.sayHello("ITeaConf");

Slide 122

Slide 122 text

122 JNA __declspec(dllexport) void __stdcall sayHello(const char* name) { printf("Hello %s from native!\n", name); } MyNativeLib.c public interface MyNativeLibrary extends Library { MyNativeLibrary INSTANCE = (MyNativeLibrary) Native.load("MyNativeLib", MyNativeLibrary.class); void sayHello(String name); } MyNativeLibrary.INSTANCE.sayHello("ITeaConf"); TestJNA.java $ java -Djava.library.path=./lib TestJNA Hello ITeaConf from native!

Slide 123

Slide 123 text

123 JNA Поддерживается: ✓ Передача, возврат по значению ✓ Указатели, C-like массивы, C-like строки ✓ Указатели на функции ✓ Struct & Union ✓ varargs

Slide 124

Slide 124 text

124 JNA Самое вкусное: ✓ Заготовлены Java описания для многих популярных C библиотек ○ LibC, X11, udev, ... ○ Kernel32, Pdh, Psapi, ... github.com/java-native-access/jna#jna-platform

Slide 125

Slide 125 text

125 JNA WinBase.SYSTEMTIME systemTime = new WinBase.SYSTEMTIME(); Kernel32.INSTANCE.GetSystemTime(systemTime); System.out.println("System time: " + systemTime); System time: 31 октября 2021 г., 14:08:03

Slide 126

Slide 126 text

126 JNA WinBase.SYSTEMTIME systemTime = new WinBase.SYSTEMTIME(); Kernel32.INSTANCE.GetSystemTime(systemTime); System.out.println("System time: " + systemTime); Psapi.PERFORMANCE_INFORMATION info = new Psapi.PERFORMANCE_INFORMATION(); Psapi.INSTANCE.GetPerformanceInfo(info, 104); System.out.println("commited mem = " + info.CommitTotal); System.out.println("physical mem = " + info.PhysicalTotal); commited mem = 3357974 physical mem = 2069169 System time: 31 октября 2021 г., 14:08:03

Slide 127

Slide 127 text

127 JNA - подводные камни

Slide 128

Slide 128 text

128 JNA - подводные камни ВСЁ ЕЩЁ МЕДЛЕННЕЕ

Slide 129

Slide 129 text

129 JNA - подводные камни Java ⇒ Java - прямой вызов Java метода без инлайна Java ⇒ Native - вызов нативного метода (без параметров) из Java Разница в 6 раз OpenJDK 17.0.1

Slide 130

Slide 130 text

130 JNA - подводные камни Java ⇒ Native (JNI) - вызов нативного метода (без параметров) из Java Java ⇒ Native (JNA) - вызов нативного метода чрез JNA OpenJDK 17.0.1

Slide 131

Slide 131 text

131 JNA - подводные камни Java ⇒ Native (JNI) - вызов нативного метода (без параметров) из Java Java ⇒ Native (JNA) - вызов нативного метода чрез JNA Разница в 7.5 раз (в 42 раза от вызова Java версии) OpenJDK 17.0.1

Slide 132

Slide 132 text

Производительность JNA 132 ✓ Все базируется на JNI, поэтому быстрее быть точно не может

Slide 133

Slide 133 text

Как позвать натив? 133 Как себя должен вести GC? Где взять нативы? Как работать с Java из натива?

Slide 134

Slide 134 text

Как позвать натив? 134 Как себя должен вести GC? Где взять нативы? Как работать с Java из натива?

Slide 135

Slide 135 text

Производительность JNA 135 ✓ Все базируется на JNI, поэтому быстрее быть точно не может ✓ Поиск реализаций: на стороне Java - Reflection, на стороне натива огромный dispatch MyNativeLibrary.INSTANCE.sayHello("ITeaConf"); com.sun.jna.Natives.invokeVoid(...) com.sun.jna.Function.invoke(...) void __stdcall sayHello(const char* name)

Slide 136

Slide 136 text

Производительность JNA 136 ✓ Все базируется на JNI, поэтому быстрее быть точно не может ✓ Поиск реализаций: на стороне Java - Reflection, на стороне натива огромный dispatch ✓ Мусорит Java обертками вокруг нативых сущностей (Pointer, Memory, ByReference)

Slide 137

Slide 137 text

А есть еще варианты? 137

Slide 138

Slide 138 text

А есть еще варианты? 138 ✓ JNR - Java Native Runtime

Slide 139

Slide 139 text

А есть еще варианты? 139 ✓ JNR - Java Native Runtime ○ работает НАМНОГО быстрее JNA

Slide 140

Slide 140 text

JNR - производительность 140 OpenJDK 17.0.1

Slide 141

Slide 141 text

JNR - производительность 141 OpenJDK 17.0.1

Slide 142

Slide 142 text

JNR - производительность 142 OpenJDK 17.0.1

Slide 143

Slide 143 text

А есть еще варианты? 143 ✓ JNR - Java Native Runtime ○ работает НАМНОГО быстрее JNA (но не быстрее JNI)

Slide 144

Slide 144 text

А есть еще варианты? 144 ✓ JNR - Java Native Runtime ○ работает НАМНОГО быстрее JNA (но не быстрее JNI) ○ но меньше оберток для библиотек и работает не на всех платформах

Slide 145

Slide 145 text

А есть еще варианты? 145 ✓ JNR - Java Native Runtime ○ работает НАМНОГО быстрее JNA (но не быстрее JNI) ○ но меньше оберток для библиотек и работает не на всех платформах ✓ JavaCPP

Slide 146

Slide 146 text

А есть еще варианты? 146 ✓ JNR - Java Native Runtime ○ работает НАМНОГО быстрее JNA (но не быстрее JNI) ○ но меньше оберток для библиотек и работает не на всех платформах ✓ JavaCPP ○ работает намного* быстрее JNA (но не быстрее JNI)

Slide 147

Slide 147 text

147 JavaCPP OpenJDK 17.0.1

Slide 148

Slide 148 text

А есть еще варианты? 148 ✓ JNR - Java Native Runtime ○ работает НАМНОГО быстрее JNA (но не быстрее JNI) ○ но меньше оберток для библиотек и работает не на всех платформах ✓ JavaCPP ○ работает намного* быстрее JNA (но не быстрее JNI) ○ предназначен для связи с C++ кодом

Slide 149

Slide 149 text

1. JNA, JNR, JavaCPP - повышают удобство интеропа 2. С ними больше никакого кода на C/C++ 3. Платим производительностью и иногда корректностью 4. Детальный разбор здесь: https://www.youtube.com/watch?v=DVTeZdtuHS0 149 Takeaways про библиотеки

Slide 150

Slide 150 text

150 Что день готовит нам грядущий?

Slide 151

Slide 151 text

151 Project Panama

Slide 152

Slide 152 text

152 Project Panama ✓ Что: мега-проект в JDK (since 2014) ✓ Зачем: легкость использования С/С++ библиотек и нативного кода из Java ✓ Как: вместо написания кода на C/C++ расширить возможности Java

Slide 153

Slide 153 text

153 Project Panama ✓ Memory Access API (JEP 370, 383, 393) ○ Новый API для работы с нативной памятью ○ Потенциальная замена ByteBuffer ○ Incubator-модуль в Java 14, 15, 16, 17

Slide 154

Slide 154 text

154 Project Panama ✓ Memory Access API (JEP 370, 383, 393) ✓ Новый Foreign Function Interface (JEP 191, 412, 419) ○ Native Method Handles ○ MemorySegment from Memory Access API ○ jextract для генерации интерфейсов ○ Incubator-модуль в Java 17

Slide 155

Slide 155 text

155 Project Panama ✓ Memory Access API (JEP 370, 383, 393) ✓ Новый Foreign Function Interface (JEP 191, 412, 419) ○ Native Method Handles ○ MemorySegment from Memory Access API ○ jextract для генерации интерфейсов ○ Incubator-модуль в Java 17 ✓ Vector API (JEP 338, 414)

Slide 156

Slide 156 text

Project Panama void test(void) { printf("Hello from Panama!\n"); } void testUpcall(void (*upcall)(void)) { upcall(); } panamatest.c void test(void); void testUpcall(void (*upcall)(void)); panamatest.h 156

Slide 157

Slide 157 text

static { System.loadLibrary("panamatest"); } static CLinker LINKER = CLinker.getInstance(); static SymbolLookup loaderLookup = SymbolLookup.loaderLookup(); static final MethodHandle downcallMH = LINKER.downcallHandle(loaderLookup.lookup("test").get(), MethodType.methodType(void.class), FunctionDescriptor.ofVoid()); Project Panama 157 jdk-17.0.1

Slide 158

Slide 158 text

static { System.loadLibrary("panamatest"); } static CLinker LINKER = CLinker.getInstance(); static SymbolLookup loaderLookup = SymbolLookup.loaderLookup(); static final MethodHandle downcallMH = LINKER.downcallHandle(loaderLookup.lookup("test").get(), MethodType.methodType(void.class), FunctionDescriptor.ofVoid()); Project Panama 158 jdk-17.0.1

Slide 159

Slide 159 text

static { System.loadLibrary("panamatest"); } static CLinker LINKER = CLinker.getInstance(); static SymbolLookup loaderLookup = SymbolLookup.loaderLookup(); static final MethodHandle downcallMH = LINKER.downcallHandle(loaderLookup.lookup("test").get(), MethodType.methodType(void.class), FunctionDescriptor.ofVoid()); Project Panama 159 downcallMH.invokeExact(); jdk-17.0.1

Slide 160

Slide 160 text

static { System.loadLibrary("panamatest"); } static CLinker LINKER = CLinker.getInstance(); static SymbolLookup loaderLookup = SymbolLookup.loaderLookup(); static final MethodHandle downcallMH = LINKER.downcallHandle(loaderLookup.lookup("test").get(), MethodType.methodType(void.class), FunctionDescriptor.ofVoid()); Project Panama 160 downcallMH.invokeExact(); $ java --add-modules=jdk.incubator.foreign \ --enable-native-access=ALL-UNNAMED \ -Djava.library.path=./lib TestPanama jdk-17.0.1

Slide 161

Slide 161 text

static { System.loadLibrary("panamatest"); } static CLinker LINKER = CLinker.getInstance(); static SymbolLookup loaderLookup = SymbolLookup.loaderLookup(); static final MethodHandle downcallMH = LINKER.downcallHandle(loaderLookup.lookup("test").get(), MethodType.methodType(void.class), FunctionDescriptor.ofVoid()); Project Panama 161 downcallMH.invokeExact(); $ java --add-modules=jdk.incubator.foreign \ --enable-native-access=ALL-UNNAMED \ -Djava.library.path=./lib TestPanama WARNING: Using incubator modules: jdk.incubator.foreign Hello from Panama! jdk-17.0.1

Slide 162

Slide 162 text

Project Panama 162 void test(void) { printf("Hello from Panama!\n"); } void testUpcall(void (*upcall)(void)) { upcall(); } panamatest.c void test(void); void testUpcall(void (*upcall)(void)); panamatest.h Возвращаемся в Java код через указатель на Java функцию;

Slide 163

Slide 163 text

Project Panama 163 void test(void) { printf("Hello from Panama!\n"); } void testUpcall(void (*upcall)(void)) { upcall(); } panamatest.c void test(void); void testUpcall(void (*upcall)(void)); panamatest.h Возвращаемся в Java код через указатель на Java функцию; Java объекты в нативный код больше не попадают! (кроме ну очень специальных, типа MemoryAddress)

Slide 164

Slide 164 text

Project Panama: jextract void test(void) { printf("Hello from Panama!\n"); } void testUpcall(void (*upcall)(void)) { upcall(); } panamatest.c void test(void); void testUpcall(void (*upcall)(void)); panamatest.h 164

Slide 165

Slide 165 text

Project Panama: jextract void test(void) { printf("Hello from Panama!\n"); } void testUpcall(void (*upcall)(void)) { upcall(); } panamatest.c jextract void test(void); void testUpcall(void (*upcall)(void)); panamatest.h 165

Slide 166

Slide 166 text

package org.sample; public final class panamatest_h { public static MethodHandle test$MH() { return panamatest_h$constants.test$MH(); } public static void test () { try { panamatest_h$constants.test$MH().invokeExact(); } catch (Throwable ex) { throw new AssertionError(ex); } } ... } panamatest_h.java Project Panama: jextract 166

Slide 167

Slide 167 text

167 А что там с производительностью? Project Panama

Slide 168

Slide 168 text

168 Project Panama Java ⇒ Native (JNI) - вызов нативного метода (без параметров) из Java OpenJDK 16-internal+0-adhoc.user.panama-foreign-CallIntrinsicsFinal2

Slide 169

Slide 169 text

169 Project Panama Java ⇒ Native (JNI) - вызов нативного метода (без параметров) из Java Java ⇒ Native (Panama) - вызов нативного метода (без параметров) из Java через MethodHandle +4% OpenJDK 16-internal+0-adhoc.user.panama-foreign-CallIntrinsicsFinal2

Slide 170

Slide 170 text

170 Project Panama Java ⇒ Native (JNI) - вызов нативного метода (без параметров) из Java Java ⇒ Native (Panama) - вызов нативного метода (без параметров) из Java через MethodHandle +6.7% OpenJDK 17.0.1

Slide 171

Slide 171 text

171 Project Panama Java ⇒ Native ⇒ Java (JNI) - upcall в Java через вызов метода переданного объекта Java ⇒ Native ⇒ Java (Panama 17) - upcall через указатель на функцию и MethodHandle +8% OpenJDK 17.0.1

Slide 172

Slide 172 text

172 Project Panama: что читать ✓ Мейлинг лист проекта: mail.openjdk.java.net/mailman/listinfo/panama-dev ✓ Описание текущего состояния: github.com/openjdk/panama-foreign/...

Slide 173

Slide 173 text

173 Project Panama: что смотреть youtu.be/4vHMmLqF09Y youtu.be/0y6_RDga-fk

Slide 174

Slide 174 text

Заключение ✓ Старайтесь не писать нативный код (там горные тролли) 174

Slide 175

Slide 175 text

Заключение ✓ Старайтесь не писать нативный код (там горные тролли) ✓ Знайте свой путь в Мордор фреймворк для вызова нативного кода youtube.com/watch?v=DVTeZdtuHS0 175

Slide 176

Slide 176 text

Заключение ✓ Старайтесь не писать нативный код (там горные тролли) ✓ Знайте свой путь в Мордор фреймворк для вызова нативного кода youtube.com/watch?v=DVTeZdtuHS0 ✓ Native ⇔ managed переходы в Java - все еще открытый вопрос! 176

Slide 177

Slide 177 text

Q & A t.me/jugnsk [email protected] @dbg_nsk бенчмарки здесь: github.com/ugliansky/jpoint2020