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:

  1. If the java package name is a.b.c and the class name is ClassName, the parameter passed into (*env)->FindClass should be converted to (*env)->FindClass(env, "a/b/c/ClassName");
  2. 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.
  3. Set ignoreUnrecognized to JNI_FALSE for more error message like Unrecognized option:.
  4. 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 includes yourpath/Home/bin/java, then yourpath/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.
  5. 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

Reference