實驗代碼已打包,下載地址。
實現原理:使用JNI提供的接口來反射得到Java方法,進行調用。jni.h在JDK裏(jdk1.8.0_121/include/)。
(通過JNI可以實現java調用C,也可以實現C調用java)
HelloWorld.java:
public class HelloWorld{
public static void main(String[] args){
System.out.println("Hello, World");
}
public static int square(int input){
int output = input * input;
return output;
}
public static int power(int input, int exponent){
int output,i;
output=1;
for(i=0;i<exponent;i++){
output *= input;
}
return output;
}
}
hello_world.c:
#include<stdio.h>
#include<jni.h>
JNIEnv* create_vm(JavaVM **jvm)
{
JNIEnv* env;
JavaVMInitArgs args;
JavaVMOption options;
args.version = JNI_VERSION_1_6;
args.nOptions = 1;
options.optionString ="-Djava.class.path=./";
args.options = &options;
args.ignoreUnrecognized = 0;
int rv;
rv = JNI_CreateJavaVM(jvm,(void**)&env, &args);
if (rv < 0 || !env)
printf("Unable to Launch JVM%d\n",rv);
else
printf("Launched JVM! :)\n");
return env;
}
void invoke_class(JNIEnv* env)
{
jclass hello_world_class;
jmethodID main_method;
jmethodID square_method;
jmethodID power_method;
jint number=20;
jint exponent=3;
hello_world_class =(*env)->FindClass(env, "HelloWorld");
main_method =(*env)->GetStaticMethodID(env, hello_world_class, "main","([Ljava/lang/String;)V");
square_method =(*env)->GetStaticMethodID(env, hello_world_class, "square","(I)I");
power_method =(*env)->GetStaticMethodID(env, hello_world_class, "power","(II)I");
(*env)->CallStaticVoidMethod(env,hello_world_class, main_method, NULL);
printf("%d squared is %d\n",number,
(*env)->CallStaticIntMethod(env,hello_world_class, square_method, number));
printf("%d raised to the %d power is%d\n", number, exponent,
(*env)->CallStaticIntMethod(env,hello_world_class, power_method, number, exponent));
}
int main(int argc,char **argv)
{
JavaVM *jvm;
JNIEnv *env;
env = create_vm(&jvm);
if(env == NULL)
return 1;
invoke_class(env);
return 0;
}
# 編譯java
javac HelloWorld.java
# 編譯C
gcc -D__int64="long long" -Ic:/java/jdk1.8.0_121/include/ -Ic:/java/jdk1.8.0_121/include/win32 -ohello_world hello_world.c -L c:/java/jdk1.8.0_121/jre/bin/server -ljvm
要點:
a) 使用64位的JDK需要添加-D__int64="longlong"
b) 通過-I參數指定jni.h、jni_md.h的路徑。
c) 通過-L指定jvm.dll的路徑。
這3個文件都在JDK文件夾裏面,可以通過搜索找到具體的路徑。
#運行程序
hello_world
如果報找不到jvm.dll的錯,把jvm.dll(路徑:jdk1.8.0_121\jre\bin\server)註冊到系統。
具體如何註冊參考這篇文章:https://jingyan.baidu.com/article/fb48e8be3212766e632e147f.html
可以寫Makefile一步到位,Makefile:
all: run
HelloWorld.class: HelloWorld.java
javac HelloWorld.java
hello_world: hello_world.c
gcc -D__int64="long long" -Ic:/java/jdk1.8.0_121/include/-Ic:/java/jdk1.8.0_121/include/win32 -o hello_world hello_world.c -Lc:/java/jdk1.8.0_121/jre/bin/server -ljvm
run: HelloWorld.class hello_world
./hello_world
clean:
rm -f HelloWorld.class hello_world
編譯和運行:
>make
輸出結果:
javac HelloWorld.java
gcc -Ic:/java/jdk1.8.0_121/include/ -Ic:/java/jdk1.8.0_121/include/win32 -ohello_world hello_world.c -L c:/java/jdk1.8.0_121/jre/bin/server -ljvm
./hello_world
Launched JVM! :)
Hello, World
20 squared is 400
20 raised to the 3power is 8000