开发者

JNI - "Cannot open include file: 'jni_md.h'"

This sample program is meant to call a native method written in C.

Java Code

class HelloWorld {

    private native void print();

    public static void main( String args[] ) {
        new HelloWorld().print();
    }

    static {
        System.loadLibrary("HelloWorld");
    }

}

After writing this i compiled the program and generated a JNI style header file.

The header file generated is :

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <C:\Program Files\Java\jdk1.7.0\include\jni.h>
/* Header for class HelloWorld */

#ifndef _Included_HelloWorld
#define _Included_HelloWorld
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     HelloWorld
 * Method:    print
 * Signature: ()V
 */
 JNIEXPORT void JNICALL Java_Hell开发者_C百科oWorld_print
 (JNIEnv *, jobject);

 #ifdef __cplusplus
 }
 #endif
 #endif

And the native method written in c

#include <C:\Program Files\Java\jdk1.7.0\include\jni.h>
#include <C:\Program Files\Java\jdk1.7.0\include\win32\jni_md.h>
#include <stdio.h>
#include "HelloWorld.h"

JNIEXPORT void JNICALL Java_HelloWorld_print( JNIENv *env , jobject obj) {
    printf("Hello World!\n");
    return;
}

The error I get on compiling is fatal error C1083: Cannot open include file: 'jni_md.h': No such file or directory

Also my compiler underlines jobject obj saying that this class does not have storage class or specifier . It underlines *env saying expected a ')'.

Why do I get this error ?


I suspect that jni.h is trying to #include <jni_md.h>, which is then failing because you haven't added its location to your include path.

Try adding both of these entries to your C compiler's include path:

  • C:\Program Files\Java\jdk1.7.0\include
  • C:\Program Files\Java\jdk1.7.0\include\win32

The win32 path might not be necessary, depending on how jni.h is set up.


Try this,

HelloWorld.c

#include "HelloWorld.h"
#include <stdio.h>

JNIEXPORT void JNICALL Java_HelloWorld_print(JNIEnv *env, jobject obj)
{
  printf("Hello World!\n");
  return;
}

Compile it using cl.exe (I'm using VC++ and CL.EXE required following command line switches.)

c:\>cl -c /I"c:\Program Files\java\jdk1.7.0\include" /I"c:\Prog ram Files\java\jdk1.7.0\include\win32" HelloWorld.c

Link .obj module

c:\>link /libpath="c:\Program Files\java\jdk1.7.0\lib" HelloWorld.obj /dll


A Simple Java Native Interface (JNI) example in Java

  • env:jdk8、macOS 10.15
// Main.java
public class Main {
    public native int intMethod(int i);
    static {
        System.loadLibrary("Main");
    }
    public static void main(String[] args) {
        System.out.println(new Main().intMethod(2));
    }
}
// Main.c:
#include "Main.h"

JNIEXPORT jint JNICALL Java_Main_intMethod(
    JNIEnv *env, jobject obj, jint i)
{
    return i * i;
}

Compile and run:

javac Main.java -h .
gcc -dynamiclib -O3 \
    -I/usr/include \
    -I$JAVA_HOME/include \
    -I$JAVA_HOME/include/darwin \
    Main.c -o libMain.dylib
java -cp . -Djava.library.path=$(pwd) Main

Output:

4


I had this issue once, my solution was actually to edit the jni.h's internal #include from "jni_md.h" to "win32/jni_md.h", although there is probably a less hacky way you are supposed to do it.


You should include the following header file in your native code first

#include <jni.h>

In my case in UNIX system,

  • This header file jni.h is present at /usr/lib/jvm/java-8-openjdk-amd64/include/

  • Also, jni_md.h is present at /usr/lib/jvm/java-8-openjdk-amd64/include/linux

You can get the path to above files if you know where the Java installation path redirects you in your system. Get it done by following set of commands.

whereis java
/usr/bin/java /usr/share/java /usr/share/man/man1/java.1.gz

ls -l /usr/bin/java
/usr/bin/java -> /etc/alternatives/java

ls -l /etc/alternatives/java
/etc/alternatives/java -> /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java

where (->) is symbolic link.

  • At last, you get your Java installation path. In my case, it is /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java

Also don't forget to include jni.h & jni_md.h files path while doing their native Compilation.

Compilation:-

gcc -I /usr/lib/jvm/java-8-openjdk-amd64/include/ -I /usr/lib/jvm/java-8-openjdk-amd64/include/linux/ -o libHelloWorld.so -shared *nativeSourceCodeFile*.c

where (-I) is Identify the Path.

  • Above command compiles our native code & that's why path of Java Native Interface header file jni.h is provided in reference.
  • jni.h does the explicit import of jni_md.h ie. #include "jni_md.h" & that's why we've provided next reference in our compilation to that jni_md.h file.
  • jni_md.h contains the machine-dependent typedefs for jbyte, jint and jlong.

Execution:-

java -Djava.library.path=. HelloWorld

Next,

JNIEXPORT void JNICALL Java_HelloWorld_print( JNIEnv* env , jobject obj){
    printf("Hello World!\n");
}

Just see the small changes made and try to implement it.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜