Java Native Interface(JNI))の不可欠な部分は、Cヘッダーを介したJVMコードとネイティブコードのブリッジです。これらのヘッダーファイルを生成する方法は非常に単純でした。クラスファイルのコマンドラインユーティリティjavah
このプロセスにより、native
修飾子でマークされたメソッドのプロトタイプが生成されます。
Java 10の時点で、ただしjavah
ユーティリティ 削除されました 、およびその推奨される置き換えは、javacの新しいフラグ "-h"です。 Javaソースファイルが利用可能であれば、置換は正常に機能しますが、コンパイルされたクラスファイルしか利用できない場合は不十分です。(この疑問を引き起こした問題は、私がJNIを生成しようとしていることです。 Scalaソースからのバインディング。私の現在のアプローチは、最初にそれらをコンパイルしてから、結果のクラスファイルに対してjavahを実行することでした。)
コンパイルされたクラスファイルしか使用できない状況で、javah
を使用する方法と同様に、Cヘッダーファイルを生成する方法はありますか?
gjavah を使用して、JNIヘッダーファイルを生成できます。
いつでも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ソースコード、私が自由に使えるツールがあるのは悪い考えではないと思います。