For someone who wants to use Java code in C by JNI, you can call by jni with Java class or JAR(Java ARchive). Here is an example of how to let C call function in jar by JNI.
Notes:
- If the java package name is
a.b.c
and the class name isClassName
, the parameter passed into(*env)->FindClass
should be converted to(*env)->FindClass(env, "a/b/c/ClassName");
- Set the option
-Djava.class.path=./your_jar_or java_class_file_location
in JavaVMOption well. Use ‘:’ in Unix or ‘;’ in Windows as a seperator if having multiple jars. - Set ignoreUnrecognized to JNI_FALSE for more error message like
Unrecognized option:
. - To find where’s the jni.h and jni_md.h:
- On Mac:
/usr/libexec/java_home -v 1.8
find $(/usr/libexec/java_home -v 1.8) -name jni.h
find $(/usr/libexec/java_home -v 1.8) -name jni_md.h
- On Linux:
ls -a $(which java)
. Should get a path which includesyourpath/Home/bin/java
, thenyourpath/Home
is the value needs to be set as JAVA_HOME. In my case it’s/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home
.- Search those .h file in this path.
- Read jni.h for functions and types that we can use.
Main.java
package com.leexun.jnitest
public class Main {
public static void main(String[] args) {
System.out.println("Hello! World!");
}
}
main.c
#include <jni.h>
int main(int argc, char **argv)
{
JavaVM *jvm;
JNIEnv *env;
JavaVMInitArgs jvm_args;
jint result;
jclass cls;
JavaVMOption options[1];
options[0].optionString = "-Djava.class.path=./your_jar_or java_class_file_location";
jvm_args.options = options;
jvm_args.nOptions = 1;
jvm_args.version = JNI_VERSION_1_8; // Same as Java version
jvm_args.ignoreUnrecognized = JNI_FALSE; // For more error messages.
res = JNI_CreateJavaVM(&jvm, (void **)&env, &jvm_args);
if (res != JNI_OK)
{ // JNI_OK == 0
printf("Failed to create Java VM\n");
return 1;
}
cls = (*env)->FindClass(env, "com/leexun/jnitest/Main");
if (cls == NULL)
{
printf("Failed to find Main class\n");
return 1;
}
// For how to use it I will update it later.
return 0;
}
Makefile
CC = gcc
build:
$(CC) jni.c \
-I$$(/usr/libexec/java_home -v 1.8)/include/ \
-I$$(/usr/libexec/java_home -v 1.8)/include/darwin \
-L$$(/usr/libexec/java_home -v 1.8)/jre/lib/jli \
-L$$(/usr/libexec/java_home -v 1.8)/jre/lib/server/ \
-ljvm
run:
LD_LIBRARY_PATH=$$(/usr/libexec/java_home -v 1.8)/jre/lib/server/ \
./a.out