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

GoからJavaのライブラリを使う #golangtokyo

GoからJavaのライブラリを使う #golangtokyo

2017-12-11 golang.tokyo #11
https://github.com/juntaki/javago
https://github.com/juntaki/jnigo

JNIでCからJavaのライブラリを呼び出す
https://qiita.com/juntaki/items/328d307583f406abc962

De059f612e2f68589831e4bde0f15c83?s=128

Jumpei Takiyasu

December 11, 2017
Tweet

Transcript

  1. Goから Javaのライブラリを使う 滝安 純平 (juntaki) 2017-12-11 golang.tokyo #11

  2. = &Me{ Name: "Jumpei Takiyasu", Company: "M3, Inc.", Github: "juntaki",

    Twitter: "juntaki", Web: "https://juntaki.com", }
  3. エムスリーって何の会社? 医療に関するWebサービスを多数展開 • 日本で約25万人の医師会員 • 全世界で約400万人の医師会員

  4. Goから Javaのライブラリを使う

  5. 背景

  6. それGoでもできるよ (って言いたかっただけ)

  7. どうやるのか Go C Java cgo JNI cgoと、Java Native Interface(JNI)を使います

  8. Java Native Interface(JNI)とは? CやC++から、Javaを実行するためのインターフェース 詳細はエムスリー Advent Calender1日目@Qiitaで!

  9. つくりました juntaki/jnigo JNIのインターフェースをGoでラップしたもの juntaki/javago Javaのライブラリからjnigoを使ったラッパーライブラリを生成 するコマンド

  10. 使い方 1. javagoコマンドを実行すると./javaにライブラリができる 2. “./java”をimportする $ javago --classfile java.lang.Math package

    main import "fmt" import "./java" func main() { val, _ := java.Mathexp(0.5) fmt.Println(val) }
  11. juntaki/jnigoの仕組み

  12. JNIをGoから使いやすくするライブラリ Go-C-Java間の変換 • cgoでJNIの関数をラップする • GoのオブジェクトとJNIの変数の相互変換 メモリ管理 • JavaとGoのGCタイミングを合わせる •

    Cのメモリ管理をする パフォーマンス対策 探索済みクラス、メソッドIDのキャッシュ
  13. メモリ管理 JavaとCの変数をGoのオブジェクトでラップ runtime.Finalizerでまとめて開放 GoObject C (JNI) Java GetObject / malloc

    GetObject Object reference Pointer to Object ref. NewGlobalRef Go GC runtime.Finalizer DeleteGlobalRef free Java GC
  14. パフォーマンス対策 参考:Java Native Interface を使用する上でのベスト・プラクティス https://www.ibm.com/developerworks/jp/java/library/j-jni/index.html // FQCNでクラスを取得 jclass clazz

    = (*env)->FindClass(env, "Test"); // メソッド名とシグニチャで、メソッドIDを取得 jmethodID id = (*env)->GetStaticMethodID(env, clazz, "hello", "()V"); // 取得したクラスとメソッドID、引数を渡してメソッドを呼び出す。 (*env)->CallStaticVoidMethodA(env, clazz, id, NULL); クラスとメソッドIDは キャッシュして使いまわせる
  15. juntaki/javagoの仕組み

  16. javapコマンドをパースしてコード生成 Javaっぽくjnigoを呼び出せるようにする $ javap -p -s java.lang.Math Compiled from "Math.java"

    public final class java.lang.Math { public static final double E; descriptor: D … public static float max(float, float); descriptor: (FF)F public static double max(double, double); descriptor: (DD)D (DD)D: 引数Double2つ 戻り値Doubleの意味
  17. Javaっぽさ func Mathmax(args ...interface{}) (jnigo.JObject, error) { convertedArgs, err :=

    jvm.ConvertAll(args) if err != nil { return nil, err } sigArgs := "" for _, arg := range convertedArgs { sigArgs += arg.Signature() } sigMap := map[string]string{"JJ":"(JJ)J", "FF":"(FF)F", "DD":"(DD)D", "II":"(II)I"} return jvm.CallStaticFunction( "java/lang/Math", "max", sigMap[sigArgs], convertedArgs) } メソッドオーバーロードをリフレクションで実現 コンパイル時に型チェックはできず、実行時に落ちるのが難点・・ Switch function signature by argument signatures
  18. まとめ 既存のJavaコードが使いたい? →それGoでもできるよ!