无法使用 JDK11 javac 为仅变量类文件创建 JNI 头文件

Geo*_*apa 7 java java-native-interface javac java-8 java-11

我想将我的 java 程序从 JDK8 迁移到 JDK11。我解决了由 JDK11 中删除的 API 引起的构建错误。

但是,我遇到了 JNI 相关的问题。

为了解释这个问题,让我们假设我们有以下 java 文件。

package mypkg;

public class JNITest {
    static final int X_MINOR_MASK = 1;
}
Run Code Online (Sandbox Code Playgroud)

如您所见,它只有一个 int 变量,并且没有定义任何方法。

当我使用JDK8生成JNI头文件时,我执行以下步骤。
1) 编译

javac -sourcepath ./mypkg -d $OUTPUT_DIR ./mypkg/JNITest.java
Run Code Online (Sandbox Code Playgroud)

2)生成标题

javah -jni -d $OUTPUT_DIR/jni -cp ./$OUTPUT_DIR mypkg.JNITest
Run Code Online (Sandbox Code Playgroud)

然后,它生成一个头文件(mypkg_JNITest.h),如下所示:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class mypkg_JNITest */

#ifndef _Included_mypkg_JNITest
#define _Included_mypkg_JNITest
#ifdef __cplusplus
extern "C" {
#endif
#undef mypkg_JNITest_X_MINOR_MASK
#define mypkg_JNITest_X_MINOR_MASK 1L
#ifdef __cplusplus
}
#endif
#endif

Run Code Online (Sandbox Code Playgroud)

如您所知,JDK11 不再支持 javah。我们必须使用 'javac -h' 而不是它。

所以,我编译了如下的java文件。

javac -h ./$OUTPUT_DIR/jni -sourcepath ./mypkg -d $OUTPUT_DIR ./mypkg/JNITest.java
Run Code Online (Sandbox Code Playgroud)

它编译得很好,但没有生成 jni 文件。

为了测试它是否在具有本机方法时生成 jni 文件,我尝试使用以下 java 文件。

package mypkg;

public class JNITest {
    static final int X_MINOR_MASK = 1;
    public native int intMethod(int n);
}
Run Code Online (Sandbox Code Playgroud)

然后,它成功生成了一个 JNI 文件,如下所示。

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class mypkg_JNITest */

#ifndef _Included_mypkg_JNITest
#define _Included_mypkg_JNITest
#ifdef __cplusplus
extern "C" {
#endif
#undef mypkg_JNITest_X_MINOR_MASK
#define mypkg_JNITest_X_MINOR_MASK 1L
/*
 * Class:     mypkg_JNITest
 * Method:    intMethod
 * Signature: (I)I
 */
JNIEXPORT jint JNICALL Java_mypkg_JNITest_intMethod
  (JNIEnv *, jobject, jint);

#ifdef __cplusplus
}
#endif
#endif
Run Code Online (Sandbox Code Playgroud)

最后一个问题:有没有办法用JDK11的javac为一个只定义一个'static final int'变量的java文件生成一个JNI文件?

Hol*_*ger 8

只需标记该字段 @Native

package mypkg;

import java.lang.annotation.Native;

public class JNITest {
    @Native
    static final int X_MINOR_MASK = 1;
}
Run Code Online (Sandbox Code Playgroud)

  • 这记录在 [javac 手册](https://docs.oracle.com/javase/9​​/tools/javac.htm#GUID-AEEC9F07-CB49-4E96-8BC7-BCC2C7F725C9__GUID-73FC25F0-BBE2-4AAC-9BAC- 3BFDCDE4F31D),尽管不在我首先查看的“javac -h”中。 (2认同)