Step 1: Create a Java Project
Create a new Java project (says HelloJNI), and the following Java class "HelloJNI.java":
public class HelloJNI {
static {
System.loadLibrary("hello"); // hello.dll (Windows) or libhello.so (Unixes)
}
// Declare native method
private native void sayHello();
// Test Driver
public static void main(String[] args) {
new HelloJNI().sayHello(); // invoke the native method
}
}
Step 2: Convert the Java Project to C/C++ Makefile Project
Right-click on the "HelloJNI" Java project ⇒ New ⇒ Other... ⇒ Convert to a C/C++ Project (Adds C/C++ Nature) ⇒ Next.
The "Convert to a C/C++ Project" dialog appears. In "Project type", select "Makefile Project" ⇒ In "Toolchains", select "MinGW GCC" ⇒ Finish.
Now, you can run this project as a Java as well as C/C++ project.
Step 3: Generate C/C++ Header File
Create a directroy called "jni" under the project to keep all the C/C++ codes, by right-click on the project ⇒ New ⇒ Folder ⇒ In "Folder name", enter "jni".
Create a "makefile" under the "jni" directory, by right-click on the "jni" folder ⇒ new ⇒ File ⇒ In "File name", enter "makefile" ⇒ Enter the following codes. Take note that you need to use tab (instead of spaces) for the indent.
# Define a variable for classpath
CLASS_PATH = ../bin
# Define a virtual path for .class in the bin directory
vpath %.class $(CLASS_PATH)
# $* matches the target filename without the extension
HelloJNI.h : HelloJNI.class
javah -classpath $(CLASS_PATH) $*
This makefile create a target "HelloJNI.h", which has a dependency "HelloJNI.class", and invokes the javah utiltiy on HelloJNI.class (under -classpath) to build the target header file.
Right-click on the makefile ⇒ Make Targets ⇒ Create ⇒ In "Target Name", enter "HelloJNI.h".
Run the makefile for the target "HelloJNI.h", by right-click on the makefile ⇒ Make Targets ⇒ Build ⇒ Select the target "HelloJNI.h" ⇒ Build. The header file "HelloJNI.h" shall be generated in the "jni" directory. Refresh (F5) if necessary. The outputs are:
make HelloJNI.h
javah -classpath ../bin HelloJNI
Step 4: C Implementation - HelloJNI.c
如何查找apt安装的文件安装路径?
which java
ls -lrt /usr/bin/java
ls -lrt /etc/alternatives/java
cd /usr/lib/jvm
ls
其中,/usr/lib/jvm/java-8-oracle/include表示头文件jni.h的所在路径,/usr/lib/jvm/java-8-oracle/include/linux表示头文件jni_md.h所在的路径,/usr/lib/jvm/java-8-oracle表示JDK的安装目录
target 已经建立了怎么办?right click--》build--》remove。
又有其他问题了。
--add-stdcall-alias是[minGW]特有的,删除。
还是不对
所以,看一下makefile到底是什么东西
target 相当于一个命令,build相当于执行这个命令。
clean target就是清除HelloJNI.h HelloJNI.o hello.dll,build就可以完成命令。
现在先去学一下makefile。初步学习makefile,回过头来看这个makefile文件。知道makefile文件的意思但是要从头来理清。
makefile的目的就是生产动态库函数。然后,这个java class就可以被调用了。问题是怎么写这个makefile?
- 在step3中,用了makefile便宜HelloJNI.h。成功的。看看他的语法。
- $cd ../bin是到上级目录的bin文件夹下.
- linux中PATH=$PATH:$HOME/bin是什么意思: 1. ":"代表分隔符. 2. [PATH]=$[PATH]:$[HOME]/[bin]代表在PATH环境变量中增加 $[HOME]/[bin] 这个目录
综上,CLASS_PATH = ../bin
set CLASS_PATH = 上级目录的bin文件夹下. 那我就可以推测,指的是HelloJNI.class文件,因为bin里面只有这个文件。是输入文件。
CLASS_PATH = ../bin //上级目录的bin文件夹下
vpath %.class $(CLASS_PATH) //指定.class类型文件的搜索路径是 $(CLASS_PATH)就是../bin
HelloJNI.h : HelloJNI.class
javah -classpath $(CLASS_PATH) $*
HelloJNI.h : HelloJNI.class
javah -classpath $(CLASS_PATH) $*
//指的是一条规则,目标是HelloJNI.h文件,依赖是HelloJNI.class文件。命令是`javah -classpath $(CLASS_PATH) $*`。
//`javah` 是制作头文件的命令,`-classpath`是设置路径的参数,后面跟路径,所以`$(CLASS_PATH) $*`代表路径和具体的依赖名。
//我觉得`$(CLASS_PATH)`表示路径,就相当于`../bin`,`$*`表示去掉后缀".class"的所有文件。
Java中-classpath和路径的使用
javac:如果当前你要编译的Java文件中引用了其它的类(比如说:继承),但该引用类的.class文件不在当前目录下,这种情况下就需要在javac命令后面加上-classpath参数,通过使用以下三种类型的方法 来指导编译器在编译的时候去指定的路径下查找引用类。
(1).绝对路径:javac -classpath c:/junit3.8.1/junit.jar Xxx.java
(2).相对路径:javac -classpath ../junit3.8.1/Junit.javr Xxx.java
(3).系统变量:javac -classpath %CLASSPATH% Xxx.java (注意:%CLASSPATH%表示使用系统变量CLASSPATH的值进行查找,这里假设Junit.jar的路径就包含在CLASSPATH系统变量中)
- 在step4中,要求修改makefile文件,来生成一个共享的dll库函数。在Linux下,应该是so文件。website
红色表示要修改的地方。如下:
all : hello.dll
# $@ matches the target, $< matches the first dependancy
hello.dll : HelloJNI.o
gcc -Wl,--add-stdcall-alias -shared -o $@ $<
# $@ matches the target, $< matches the first dependancy
HelloJNI.o : HelloJNI.c HelloJNI.h
gcc -I"D:\bin\jdk1.7\include" -I"D:\bin\jdk1.7\include\win32" -c $< -o $@
clean :
rm HelloJNI.h HelloJNI.o hello.dll #最简单,没有依赖,目标不是文件是空置(状态),命令是rm就是删除,注意。dll应改为so。
- “libhello.so”
- “#”表示注释
# Define a variable for classpath
CLASS_PATH = ../bin
# Define a virtual path for .class in the bin directory
vpath %.class $(CLASS_PATH)
all : libhello.so
# $@ matches the target, $< matches the first dependancy
libhello.so : HelloJNI.o
gcc -o libhello.so -shared HelloJNI.o
# $@ matches the target, $< matches the first dependancy
HelloJNI.o : HelloJNI.c HelloJNI.h
gcc -fpic -I/usr/lib/jvm/java-8-oracle/include -I/usr/lib/jvm/java-8-oracle/include/linux -c HelloJNI.c -o $@
# $* matches the target filename without the extension
HelloJNI.h : HelloJNI.class
javah -classpath $(CLASS_PATH) $*
clean :
rm HelloJNI.h HelloJNI.o libhello.so
step 5 Run the Java JNI Program
- You can run the Java JNI program HelloJNI. However, you need to provide the library path to the "hello.dll". This can be done via VM argument -Djava.library.path.
- Right-click on the project ⇒ Run As ⇒ Run Configurations ⇒ Select "Java Application"(双击new) ⇒ In "Main" tab, enter the main class "HelloJNI" ⇒ In "Arguments", "VM Arguments", enter "-Djava.library.path=jni" ⇒ Run.
-
You shall see the output "Hello World!" displayed on the console.