实验代码已打包,下载地址。
实现原理:使用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