Last active
October 28, 2016 02:09
-
-
Save dhilst/31cc7d04bbe3659beeb9321309e77db2 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
| public class JNIThread { | |
| /* This method will be called asychrounously from | |
| * native code. There is no native method because | |
| * we will use JNI_OnLoad to make the magic happens. */ | |
| public static void calledAsynchronously() { | |
| System.out.println("Asynchronous hello from Java"); | |
| } | |
| public static void main(String[] args) | |
| throws InterruptedException { | |
| /* Load our native library */ | |
| System.loadLibrary("jnithread"); | |
| /* Make sure that we give enoght time | |
| * to native thread to run. */ | |
| int n = 6; | |
| while (n-- > 0) | |
| Thread.sleep(1000); | |
| } | |
| } |
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 <assert.h> | |
| #include <unistd.h> | |
| #include "JNIThread.h" | |
| #include "pthread.h" | |
| /* This is one of the most important part of calling | |
| * java methods asynchrounously from native code. You | |
| * need a pointer to JavaVM. To make any call to Java | |
| * code we need a JNIEnv pointer. That pointer is used | |
| * to access the JNI's vtable. To get one JNIEnv we | |
| * need a pointer to JavaVM.*/ | |
| static JavaVM *JVM; | |
| /* Our native thread, keep reading */ | |
| static void *native_thread(void *unused); | |
| /* This function is called as soon as the JVM loads. | |
| * We will store the JavaVM pointer to our (file scoped) | |
| * global JVM variable. After that we simply create our | |
| * thread and return a JNI_VERSION_* of our preference. | |
| * This return code is to make JVM knows what version | |
| * of native interface we're expecting to work with. */ | |
| JNIEXPORT jint JNICALL | |
| JNI_OnLoad(JavaVM *vm, void *reserved) | |
| { | |
| JVM = vm; | |
| pthread_t t; | |
| pthread_create(&t, NULL, native_thread, NULL); | |
| return JNI_VERSION_1_1; | |
| } | |
| static void *native_thread(void *unused) | |
| { | |
| JNIEnv *env; | |
| /* Here the magic is maded. We attach our native | |
| * thread to one Java thread. This initilizes a | |
| * JNIEnv so we can call any function from JNI's | |
| * vtable. */ | |
| assert((*JVM)->AttachCurrentThread(JVM, (void **)&env, NULL) == JNI_OK); | |
| jclass JNIThread = (*env)->FindClass(env, "JNIThread"); | |
| assert(JNIThread); | |
| jmethodID calledAsynchronously = (*env)->GetStaticMethodID(env, JNIThread, "calledAsynchronously", "()V"); | |
| assert(calledAsynchronously); | |
| int n = 5; | |
| while (n-- > 0) { | |
| (*env)->CallStaticVoidMethod(env, JNIThread, calledAsynchronously); | |
| sleep(1); | |
| } | |
| /* When done we need to detach the thread so no | |
| * memory leaks happen */ | |
| assert((*JVM)->DetachCurrentThread(JVM) == JNI_OK); | |
| } |
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-8-openjdk-amd64 | |
| CFLAGS += -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/linux | |
| all: libjnithread.so | |
| libjnithread.so: libjnithread.c JNIThread.h | |
| JNIThread.h: JNIThread.class | |
| JNIThread.class: JNIThread.java | |
| %.class: %.java | |
| javac $< | |
| %.h: %.class | |
| javah $(<:.class=) | |
| %.so: %.c | |
| $(CC) $(CFLAGS) $(LDFLAGS) -fPIC -shared -o $@ $^ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment