Java 为JDK 10中的类文件生成JNI头文件
Java本机接口(JNI)的一个组成部分是通过C头连接JVM代码和本机代码。生成这些头文件的方法过去非常简单:只需对类文件调用命令行实用程序Java 为JDK 10中的类文件生成JNI头文件,java,java-native-interface,javah,java-10,Java,Java Native Interface,Javah,Java 10,Java本机接口(JNI)的一个组成部分是通过C头连接JVM代码和本机代码。生成这些头文件的方法过去非常简单:只需对类文件调用命令行实用程序javah。然后,该过程将为标记有native修饰符的任何方法生成原型 但是,从Java10开始,javah实用程序及其建议的替换是javac的一个新标志“-h”。如果有可用的Java源文件,那么替换就可以了,但是在只有编译类文件可用的情况下,替换就不够了。(引发这个问题的问题是,我试图从Scala源代码生成JNI绑定。我目前的方法是先编译它们,然后在生成的
javah
。然后,该过程将为标记有native
修饰符的任何方法生成原型
但是,从Java10开始,javah
实用程序及其建议的替换是javac的一个新标志“-h”。如果有可用的Java源文件,那么替换就可以了,但是在只有编译类文件可用的情况下,替换就不够了。(引发这个问题的问题是,我试图从Scala源代码生成JNI绑定。我目前的方法是先编译它们,然后在生成的类文件上运行javah。)
在只有编译过的类文件可用的情况下,是否有一种生成C头文件的方法,类似于
javah
过去的方法?您总是可以通过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}
我打赌它会变得更漂亮
对我来说,现在,当我慢慢开始考虑不可避免地向Java10发展时,所有这些情况下,我可能会对不存在的Java源代码感到惊讶,我认为拥有一些工具供我使用不是一个坏主意。以防万一。我们可以用来生成JNI头文件。我认为最好的解决方案就是安装jdk8。
无需卸载jdk10,只需修改环境变量。可能只是假设,但是否将scala源代码编译成jar,然后在类路径上使用jar作为
javac-h
标志不是一个选项?有一个基于javap
的丑陋解决方案。您可以反编译类,只保留本机内容,并使用javac将内容编译回来。但这是一种非常丑陋的方法,不幸的是,您提出的解决方案不起作用。javac在源代码中确实需要本机修饰符。目前,mko的答案看起来是最有希望的。关于Kotlin使用javah的类似问题:如果本机方法采用参数(javac抱怨错误:预期),这似乎不起作用。感谢您在Salomonbris发现它!!