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 ofjni_md.h
ie.#include "jni_md.h"
& that's why we've provided next reference in our compilation to thatjni_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.
精彩评论