为 JDK 10 中的 class 个文件生成 JNI header 个文件
Generate JNI header files for class files in JDK 10
Java 本机接口 (JNI) 的一个组成部分是通过 C headers 桥接 JVM 代码和本机代码。生成这些 header 文件的方法过去非常简单:只需在 class 文件上调用命令行实用程序 javah
。然后,此过程将为任何标有 native
修饰符的方法生成原型。
然而,从 Java 10 开始,javah
实用程序 has been removed 及其建议的替代品是 javac 的新标志“-h”。如果有可用的 Java 源文件,则替换工作正常,但是在只有编译的 class 文件可用的情况下,替换就不够用了。 (引发这个问题的问题是我正在尝试从 Scala 源代码生成 JNI 绑定。我目前的方法是先编译它们,然后 运行 javah 在生成的 class 文件上。)
在只有编译的class文件可用的情况下,有没有办法生成Cheader文件,类似于javah
以前的方式?
您随时可以通过 javap
。我知道我知道。它很丑陋,有很多假设,但如果您迫切需要为大量文件生成 headers,它可能是唯一的选择。
#!/bin/bash
# FIRST_ARG - full class name (with package)
# SECOND_ARG - class path
CLASS_NAME=`javap -cp | \
grep -v "Compiled from" | \
grep "public class" | \
cut -f3 -d" " | \
awk -F"." '{ print $NF }'`
PACKAGE_NAME=`javap -cp | \
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 | 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 源代码感到惊讶,我认为拥有一些可供我使用的工具并不是一个坏主意。以防万一
我们可以使用gjavah生成JNI头文件。
我认为最好的解决方案就是安装 jdk8。
而且不需要卸载jdk10,只需要修改环境变量即可。
Java 本机接口 (JNI) 的一个组成部分是通过 C headers 桥接 JVM 代码和本机代码。生成这些 header 文件的方法过去非常简单:只需在 class 文件上调用命令行实用程序 javah
。然后,此过程将为任何标有 native
修饰符的方法生成原型。
然而,从 Java 10 开始,javah
实用程序 has been removed 及其建议的替代品是 javac 的新标志“-h”。如果有可用的 Java 源文件,则替换工作正常,但是在只有编译的 class 文件可用的情况下,替换就不够用了。 (引发这个问题的问题是我正在尝试从 Scala 源代码生成 JNI 绑定。我目前的方法是先编译它们,然后 运行 javah 在生成的 class 文件上。)
在只有编译的class文件可用的情况下,有没有办法生成Cheader文件,类似于javah
以前的方式?
您随时可以通过 javap
。我知道我知道。它很丑陋,有很多假设,但如果您迫切需要为大量文件生成 headers,它可能是唯一的选择。
#!/bin/bash
# FIRST_ARG - full class name (with package)
# SECOND_ARG - class path
CLASS_NAME=`javap -cp | \
grep -v "Compiled from" | \
grep "public class" | \
cut -f3 -d" " | \
awk -F"." '{ print $NF }'`
PACKAGE_NAME=`javap -cp | \
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 | 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 源代码感到惊讶,我认为拥有一些可供我使用的工具并不是一个坏主意。以防万一
我们可以使用gjavah生成JNI头文件。
我认为最好的解决方案就是安装 jdk8。 而且不需要卸载jdk10,只需要修改环境变量即可。