Last active
October 31, 2016 22:06
-
-
Save dhilst/29cd74f42bf2d319ce793f1cd0c9b399 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// In this example I will show how to cache classes, method and field IDs. Caching | |
// these lookups can improve performance of native calls by safing native code | |
// from extra JNI calls. | |
public class JNICache { | |
// Here we load our native library at a static block. This ensures that the library | |
// is loaded as soon as the class is loaded. This will make caching simpler and safer. | |
static { | |
System.loadLibrary("cache"); | |
} | |
// These fields will be accessed by native getters. Their IDs are cached at library | |
// load time. | |
int intField; | |
String stringField; | |
// This method will be called by native code. It's methodID will be cached at library | |
// load time. | |
static void calledFromNative() { | |
System.out.println("Hello from java"); | |
} | |
// The native getters. Access object's fields. | |
native String getString(); | |
native int getInt(); | |
// A simple constructor to initialize our fields. | |
JNICache(int i, String s) { | |
intField = i; | |
stringField = s; | |
} | |
public static void main(String[] args) { | |
// Instantiate an object. | |
JNICache jc = new JNICache(args[0].length(), args[0]); | |
// Call it's native getters | |
System.out.println("JNICache { " + jc.getInt() + ", " + jc.getString() + "}"); | |
} | |
} | |
// vim: set ts=4:sw=4 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "JNICache.h" | |
#include <iostream> | |
#include <stdexcept> | |
using namespace std; | |
// This is our cache. The variables are initialized | |
// at JNI_OnLoad and used by native methods. | |
static jclass JNICache_cls = NULL; | |
static jmethodID JNICache_calledFromNative_mid = NULL; | |
static jfieldID JNICache_string_fid = NULL; | |
static jfieldID JNICache_int_fid = NULL; | |
extern "C" | |
JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) | |
{ | |
JNIEnv* env; | |
if (vm->AttachCurrentThread((void **)&env, NULL) != JNI_OK) { | |
cerr << "AttachCurrentThread failed" << endl; | |
return -1; | |
} | |
// We call FindClass to get a reference to JNICache class. | |
// That reference will be valid for the life time of JNIEnv. | |
jclass cls = env->FindClass("JNICache"); | |
if (cls == NULL) { | |
cerr << "FindClass failed for JNICache class" << endl; | |
exit(-1); | |
} | |
// To make the reference live forever we need to create a | |
// global reference. Here [1] you can read more about references. | |
// [1] http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/functions.html#global_local | |
JNICache_cls = (jclass) env->NewGlobalRef(cls); | |
if (JNICache_cls == NULL) { | |
cerr << "NewGlobalRef failed for JNICache class" << endl; | |
exit(-1); | |
} | |
// Method and field IDs can be simply saved to global variables | |
// since they don't depend on JNIEnv life time. | |
JNICache_calledFromNative_mid = env->GetStaticMethodID(JNICache_cls, "calledFromNative", "()V"); | |
if (!JNICache_calledFromNative_mid) { | |
cerr << "Cache failed for calledFromNative method" << endl; | |
exit(-1); | |
} | |
JNICache_string_fid = env->GetFieldID(JNICache_cls, "stringField", "Ljava/lang/String;"); | |
if (!JNICache_string_fid) { | |
cerr << "Cache failed for JNICache_string_fid method" << endl; | |
exit(-1); | |
} | |
JNICache_int_fid = env->GetFieldID(JNICache_cls, "intField", "I"); | |
if (!JNICache_int_fid) { | |
cerr << "Cache failed for JNICache_int_fid method" << endl; | |
exit(-1); | |
} | |
vm->DetachCurrentThread(); | |
return JNI_VERSION_1_1; | |
} | |
extern "C" | |
JNIEXPORT void JNI_OnUnload(JavaVM* vm, void* reserved) | |
{ | |
JNIEnv* env; | |
if (vm->AttachCurrentThread((void **)&env, NULL) != JNI_OK) | |
return; | |
// Delete the global reference so we don't create memory leaks. | |
env->DeleteGlobalRef(JNICache_cls); | |
vm->DetachCurrentThread(); | |
} | |
extern "C" | |
JNIEXPORT jstring JNICALL Java_JNICache_getString | |
(JNIEnv* env, jobject obj) | |
{ | |
// This call use the cached method, saving us from calling | |
// FindClass and GetStaticMethodID. In this example the | |
// class could be retrieved f | |
// with obj as its parameter. | |
// Here the cached field id is used. | |
env->CallStaticVoidMethod(JNICache_cls, JNICache_calledFromNative_mid); | |
return reinterpret_cast<jstring>(env->GetObjectField(obj, JNICache_string_fid)); | |
} | |
extern "C" | |
JNIEXPORT jint JNICALL Java_JNICache_getInt | |
(JNIEnv* env, jobject obj) | |
{ | |
env->CallStaticVoidMethod(JNICache_cls, JNICache_calledFromNative_mid); | |
return env->GetIntField(obj, JNICache_int_fid); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
JAVA_HOME = /usr/lib/jvm/java-1.8.0-openjdk-amd64 | |
TARGET := JNICache | |
TARGET_NATIVE := libcache | |
CXXFLAGS += -Wall -std=c++11 | |
CXXFLAGS += -I. -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/linux | |
all: libcache.so | |
clean: | |
rm JNICache.class libcache.so JNICache.h | |
run: | |
java -Djava.library.path=. JNICache $(TARGET_ARGS) | |
libcache.o: JNICache.h libcache.cc | |
libcache.so: libcache.o | |
JNICache.h: JNICache.class | |
JNICache.class: JNICache.java | |
%.o: %.cc | |
$(CXX) $(CXXFLAGS) $(LDFLAGS) -fPIC -c $< | |
%.so: %.o | |
$(CXX) $(CXXFLAGS) $(LDFLAGS) -shared -o $@ $< | |
%.class: %.java | |
javac $< | |
%.h: %.class | |
javah -cp . $(<:.class=) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment