Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Java から Go のメソッドを呼んでみる! JEP 419​ Foreign Function & Memory API で一緒に遊んでみた​

Java から Go のメソッドを呼んでみる! JEP 419​ Foreign Function & Memory API で一緒に遊んでみた​

2022年8月26日のJJUGナイトセミナー「おうちで!ビール片手にLT大会!」の資料です。

参考: JEP 419: Foreign Function & Memory API (Second Incubator)
ソースコード: https://github.com/YujiSoftware/duke-gopher

YujiSoftware

August 27, 2022
Tweet

More Decks by YujiSoftware

Other Decks in Technology

Transcript

  1. JVM から外に出るのは大変 Java のヘッダファイルを使って C言語でコードを記述してコンパイル JNIEXPORT void JNICALL Java_com_example_TestClass_printString (JNIEnv

    *env, jobject obj, jstring javaString) { const char *nativeString = (*env)->GetStringUTFChars(env, javaString, NULL); printf("%s¥n", nativeString); (*env)->ReleaseStringUTFChars(env, javaString, nativeString); } ​Java で native コードを呼び出すように記述して、コン パイル package com.example; public class TestClass { static { System.loadLibrary("myjni"); } public static native printString(String s); public static void main(String[] args) { JNI
  2. サンプルコード JEP 419 (仮設) private static void talk(String message) throws

    Throwable { CLinker linker = CLinker.systemCLinker(); SymbolLookup lookup = SymbolLookup.loaderLookup(); MethodHandle recv = linker.downcallHandle( lookup.lookup("talk").get(), FunctionDescriptor.of(GoString.LAYOUT, GoString.LAYOUT)); try (ResourceScope scope = ResourceScope.newConfinedScope()) { MemorySegment address = (MemorySegment) recv.invoke(scope, GoString.allocate(message, scope)); System.out.println(GoString.get(address)); } } • Java のコードを書くだけ! (抜粋)
  3. コンパイル > javac Main.java Main.java:1: エラー: パッケージjdk.incubator.foreignは表示不可です import jdk.incubator.foreign.*; ^

    (パッケージjdk.incubator.foreignはモジュールjdk.incubator.foreignで 宣言されていますが、モジュール・グラフにありません) Main.java:2: エラー: パッケージjdk.incubator.foreignは表示不可です import static jdk.incubator.foreign.ValueLayout.*; ^ (略)
  4. コンパイル > javac Main.java Main.java:1: エラー: パッケージjdk.incubator.foreignは表示不可です import jdk.incubator.foreign.*; ^

    (パッケージjdk.incubator.foreignはモジュールjdk.incubator.foreignで 宣言されていますが、モジュール・グラフにありません) Main.java:2: エラー: パッケージjdk.incubator.foreignは表示不可です import static jdk.incubator.foreign.ValueLayout.*; ^ (略)
  5. 改めてコンパイル > javac --enable-preview --source 19 Main.java Main.java:1: エラー: パッケージjdk.incubator.foreignは表示不可です

    import jdk.incubator.foreign.*; ^ (パッケージjdk.incubator.foreignはモジュールjdk.incubator.foreignで 宣言されていますが、モジュール・グラフにありません) Main.java:2: エラー: パッケージjdk.incubator.foreignは表示不可です import static jdk.incubator.foreign.ValueLayout.*; ^ (略)
  6. 改めてコンパイル > javac --enable-preview --source 19 Main.java Main.java:1: エラー: パッケージjdk.incubator.foreignは表示不可です

    import jdk.incubator.foreign.*; ^ (パッケージjdk.incubator.foreignはモジュールjdk.incubator.foreignで 宣言されていますが、モジュール・グラフにありません) Main.java:2: エラー: パッケージjdk.incubator.foreignは表示不可です import static jdk.incubator.foreign.ValueLayout.*; ^ (略)
  7. --add-modules が必要! • まだ仮設のAPI(incubator module) • 本体とは分離されている • 使用するには、明示的な指定が必要 >

    javac --add-modules=jdk.incubator.foreign Main.java 警告:実験的なモジュールを使用しています:jdk.incubator.foreign 警告1個 → クラスファイルができた!
  8. 定義を間違えていた! • Go のヘッダー • Java のコード typedef struct {

    const char *p; ptrdiff_t n; } _GoString_; private static final OfAddress POINTER = ADDRESS.withName("p"); private static final OfLong NUMBER = JAVA_LONG.withName("n"); private static final GroupLayout LAYOUT = MemoryLayout.structLayout(NUMBER, POINTER); 逆
  9. 再実行 talk("Hello Gopher! (from Duke)") return "Hello Duke! (from Gopher)"

    # EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x00007ff87c79cc69, pid=15380, tid=18228 !?
  10. 処理を間違えていた! • ポインターの扱いが違う • 範囲外までアクセスしてしまった int capacity = (int) (long)

    N.get(memory); MemoryAddress ptr = (MemoryAddress) P.get(memory); byte[] b = new byte[capacity]; for (int i = 0; i < capacity; i++) { b[i] = ptr .get(ADDRESS, i).get(JAVA_BYTE, i); ↑ これがいらない } return new String(b, StandardCharsets.UTF_8);
  11. 使用素材について • Gopher Stickers (tenntenn) • https://github.com/tenntenn/gopher-stickers • Creative Commons

    3.0 Attributions license • OpenJDK Duke Project • https://wiki.openjdk.org/display/duke/Gallery • BSD License • Redistribution of Duke images • https://yuji.software/Duke/ • BSD License