Call Cuda code in Java Through JNI

Here is a step by step instruction of compiling cuda code through JNI interface.

  1. Declared a simple native method, and called System.loadLibrary in java

package com.name.package.jniexample;

public class HelloJNI { 
    static {
    	try{
        	System.loadLibrary("hello"); 
        }
        catch(UnsatisfiedLinkError e){
        	System.err.println("Cannot load .so library.")
        	e.toString();
        }
    }
 
    private native void sayHello(String str);
 
    public static void main(String[] args) {
        new HelloJNI().sayHello();  
    }
}

  1. Compile the java file, create header file
javac $(dir)/HelloJNI.java
javah com.name.package.jniexample

Notice that the directory of calling “javac” should be exactly one level out of the directory which contains the package. Otherwise, an error “Error: Could not find class file for ‘HelloJNI’” will be popped out.

Now a .h file named “com_name_package_HelloJNI.h” will be generated like below.

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class gpumcse_src_cexample_HelloJNI */

#ifndef _Included_com_name_package_HelloJNI
#define _Included_com_name_package_HelloJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     gpumcse_src_cexample_HelloJNI
 * Method:    sayHello
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_name_package_HelloJNI_sayHello
  (JNIEnv *, jobject, jstring str);

#ifdef __cplusplus
}
#endif
#endif


  1. Include the header file in the cuda code, implemente the cuda algorithm

#include <jni.h>        // JNI header provided by JDK
#include <stdio.h>      // C Standard IO Header
#include "com_name_package_HelloJNI.h"   // Generated

#include <iostream>
#include <fstream>    

// Implementation of the native method sayHello()
JNIEXPORT void JNICALL Java_com_name_package_HelloJNI_sayHello(JNIEnv *env, jobject thisObj, jstring str) {

const jbyte *str=(const jbyte *)env->GetStringUTFChars(str, JNI_FALSE);
printf("Hello, %s.\n", str);
env->ReleaseStringUTFChars(str, (const char*)str);

return;
}


  1. compiled cuda code through nvcc, used nvcc -fPIC -o to create output fle (just like what the built in make file does) used nvcc -shared to create jnilib
sudo /usr/local/cuda-9.2/bin/nvcc -Xcompiler -fPIC -std=c++11 -I$(include_path) \
				-shared -I=$(JAVA_HOME)/include -I=$(JAVA_HOME)/include/linux \
			$(dir)/main.cu -o $(dir)/libhello.so

  1. Execute the java main function
java -Djava.library.path=/path/to/.so/file/ $(dir)/HelloJNI 

Happy!