Skip to content

Instantly share code, notes, and snippets.

@dhilst
Last active October 28, 2016 02:09
Show Gist options
  • Select an option

  • Save dhilst/31cc7d04bbe3659beeb9321309e77db2 to your computer and use it in GitHub Desktop.

Select an option

Save dhilst/31cc7d04bbe3659beeb9321309e77db2 to your computer and use it in GitHub Desktop.
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);
}
}
#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);
}
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