web-dev-qa-db-ja.com

JDK 10でクラスファイルのJNIヘッダーファイルを生成する

Java Native Interface(JNI))の不可欠な部分は、Cヘッダーを介したJVMコードとネイティブコードのブリッジです。これらのヘッダーファイルを生成する方法は非常に単純でした。クラスファイルのコマンドラインユーティリティjavahこのプロセスにより、native修飾子でマークされたメソッドのプロトタイプが生成されます。

Java 10の時点で、ただしjavahユーティリティ 削除されました 、およびその推奨される置き換えは、javacの新しいフラグ "-h"です。 Javaソースファイルが利用可能であれば、置換は正常に機能しますが、コンパイルされたクラスファイルしか利用できない場合は不十分です。(この疑問を引き起こした問題は、私がJNIを生成しようとしていることです。 Scalaソースからのバインディング。私の現在のアプローチは、最初にそれらをコンパイルしてから、結果のクラスファイルに対してjavahを実行することでした。)

コンパイルされたクラスファイルしか使用できない状況で、javahを使用する方法と同様に、Cヘッダーファイルを生成する方法はありますか?

10
Jakob Odersky

gjavah を使用して、JNIヘッダーファイルを生成できます。

5
Glavo

いつでもjavapからアクセスできます。分かった分かった。醜く、多くの仮定がありますが、多くのファイルのヘッダーを必死に生成する必要がある場合は、これが唯一のオプションとなる場合があります。

#!/bin/bash

# FIRST_ARG - full class name (with package)
# SECOND_ARG - class path

CLASS_NAME=`javap -cp $2 $1 | \
  grep -v "Compiled from" | \
  grep "public class" | \
  cut -f3 -d" " | \
  awk -F"." '{ print $NF }'`

PACKAGE_NAME=`javap -cp $2 $1 | \
  grep -v "Compiled from" | \
  grep "public class" | \
  cut -f3 -d" " | \
  sed s/\.${CLASS_NAME}$//`

DIR_NAME=`echo $PACKAGE_NAME | sed 's|\.|/|g'`
mkdir -p Java_jni/${DIR_NAME}

Java_FILE_NAME="Java_jni/${DIR_NAME}/${CLASS_NAME}.Java"

echo "package ${PACKAGE_NAME};" > ${Java_FILE_NAME}
echo "public class ${CLASS_NAME} {" >> ${Java_FILE_NAME}

javap -cp $2 $1 | grep "native" | while read line; do
  param=0
  comma=`echo $line | grep "," | wc -l`
  while [ $comma -gt 0 ]; do
    line=`echo $line | sed "s/,/ param_${param}|/"`
    let param=param+1
    comma=`echo $line | grep "," | wc -l`
  done
  line=`echo $line | sed "s/)/ param_${param})/" | sed 's/|/,/g'`
  echo "  $line" >> ${Java_FILE_NAME}
done

echo "}" >> ${Java_FILE_NAME}

mkdir -p c_header
javac -h c_header ${Java_FILE_NAME}

きっともっと美しくできるはずです。

私にとって、今、Java 10およびこれらすべてのケースに向かって、避けられない動きについてゆっくりと考え始めると、存在しないJavaソースコード、私が自由に使えるツールがあるのは悪い考えではないと思います。

5
Oo.oO