mike-neckのブログ

Java or Groovy or Swift or Golang

graalvm-native-image プラグイン 0.6.1 続いて 0.7.0 をリリースしました

表題のとおりですが、 0.5.0 をほぼ全部書き換えています。 API そのものは変更していないので、ユーザーが既存のビルドを維持する場合に現在の DSL に手を加える必要はありません

f:id:mike_neck:20191218195401p:plain

f:id:mike_neck:20200630065637p:plain

plugins.gradle.org

正確には v0.6.1 を 2020-06-21 に v0.7.0 を 2020-06-30 にリリースしました


New Feature

GraalVM native-image でネイティブバイナリーを生成する場合に、リフレクションやらリソースファイルやらを使っている場合には、 (1) json で設定ファイルを書いて、 (2) イメージ作成時にオプションで渡す必要がありました。 バージョン 0.6.0 からはこれらの json の自動生成およびオプション指定用の DSL を追加しました

(1) config json 自動生成

新たに config ファイルを生成する generateNativeImageConfig タスクと mergeNativeImageConfig タスクが追加されています。

前者のタスクではアプリケーションを複数回実行して、config json を生成します。後者のタスクでは生成された json をマージして一つのファイルにします。

これらのタスクの設定は generateNativeImageConfig {} ブロックで行います(generateNativeImageConfig タスクの設定なので、 kotlin script の場合は、 tasks {} ブロックの中で行う必要があります)

例えば、 json が入力である旨オプションを指定して、標準入力から json を受け取って何かしらの出力をするコマンドラインアプリを考えます。また、このアプリはヘルプオプションが用意されているものとします。

generateNativeImageConfig {
  enabled = true // (1)

  byRunningApplication { //(2)
    arguments("-i", "json") // (3)
    stdIn("""{
  "name": "石田三成",
  "age": 50
}""")    // (4)
  }

  byRunningApplication { // (5)
    arguments("-h")
  }
}
  1. 既存のプラグインと異なる挙動になるのを避けるため、デフォルトは機能をオフにしてあります。出力機能が欲しい場合は enabled = true を指定してください
  2. アプリケーションを実行するためのパラメーター・標準入力・環境変数の指定を行います
  3. argumentsコマンドラインアプリ起動時のオプションを指定します
  4. stdIn で標準入力の値を指定します
  5. byRunningApplicationgenerateNativeImageConfig ブロック内で何回も指定できます

このビルドスクリプトで、 generateNativeImageConfig タスクを実行すると、次のように build/tmp/native-image-config の下に実行ごとに config json が生成されます

f:id:mike_neck:20200622094014p:plain

なお、実装的には java agent に native-image-agent を指定して java を実行しているだけです。また、そのため、 web アプリケーションのような一度起動したら二度と落とすことのないアプリケーションでの利用は(多分)できません。

なお、ここで生成された config ファイルは mergeNativeImageConfig タスクによって、それぞれ 1 つずつのファイルにマージされます。実は、マージする必要ないのではないかという指摘に対しては、そのとおりなので「はい」と答えるしかないのが辛いところです


(2) nativeImage タスクに native-image config json を渡す用の DSL を追加しました

従来だと、native-image config json があった場合に、 arguments(String...) にパラメーターを作って渡す必要がありました

nativeImage {
  arguments("-H:ReflectConfigurationFiles=${file("path/to/config.json")}")
}

今回のリリースでこの設定ファイル指定用の DSL が追加されています

nativeImage {
  withConfigFiles {
    addReflectConfig(file("path/to/config.json"))
  }
}

Some improvements

Kotlin DSL を改善しました。従来は setter のみ公開していたためプロパティアクセスで設定できなかった項目を、プロパティアクセスで設定できるようにしました。なお、プロパティアクセスできるとはいえ、 get アクセスすると UnsupportedOperationException が発生します。これは内部に保持しているデータが getter 向けではないためです。

nativeImage {
  graalVmHome = "/path/to/graalvm"
  mainClass = "com.example.App"
  executableName = "awesome-utility"
}

以上、よい GraalVM native-image ライフを!

おわり

savanna-gradle-plugin をリリースしました

会社で仕事をサボってツイッター見てたら、t_wada さんのトレードマークと言えるライオンに関するツイートがいくつか流れてきました。

Gradle で同じことしてるのあるだろうと思って、「gradle savanna」で検索したところ誰も作っていないようだったので、作ってみました。

plugins.gradle.org

続きを読む

Gradle の C++ プラグインを使って JNI から C++ のコードを呼び出すアプリケーションをビルドする(Android プロジェクトではない)

GraalVM の native-image を作る際に利用する config.json を自動生成させて、アプリケーションを複数回実行してマージするというのをやろうとしており、 JNI を使う Java アプリケーション(JNA ではない)を Gradle でビルドする必要が出てきたが、残念なことに JNI で native を呼び出すアプリケーションを作ったことがなかったので、試しに作ってみることにした。

ところが、 Gradle で JNI を構築する場合の手順が Android だったり、古い software model だったりで、最近の Gradle C++ プラグインを利用しているものがないのでメモに残しておこうという理由でこれを書いてる。

続きを読む

Proxy の InvocationHandler から interface の default メソッドを呼び出す方法

  1. proxy を取得する対象のインターフェースクラスで MethodHandles.lookup() を呼び出して MethodHandles.Lookup を取得する
    1. で取得した MethodHandles.Lookupインスタンスから unreflectSpecial(Method, Class<?>) を呼び出して、MethodHandle を取得する
  2. proxy のインスタンスbindTo して invoke する
続きを読む