Get the JavaVM handle on Android targets

This commit is contained in:
Chris Robinson 2017-01-26 14:30:14 -08:00
parent 1ebfce4cac
commit f0c8b7f255
2 changed files with 72 additions and 0 deletions

View File

@ -1166,6 +1166,70 @@ static void alc_initconfig(void)
}
#define DO_INITCONFIG() alcall_once(&alc_config_once, alc_initconfig)
#ifdef __ANDROID__
#include <jni.h>
static JavaVM *gJavaVM;
static pthread_key_t gJVMThreadKey;
static void CleanupJNIEnv(void* UNUSED(ptr))
{
JCALL0(gJavaVM,DetachCurrentThread)();
}
void *Android_GetJNIEnv(void)
{
/* http://developer.android.com/guide/practices/jni.html
*
* All threads are Linux threads, scheduled by the kernel. They're usually
* started from managed code (using Thread.start), but they can also be
* created elsewhere and then attached to the JavaVM. For example, a thread
* started with pthread_create can be attached with the JNI
* AttachCurrentThread or AttachCurrentThreadAsDaemon functions. Until a
* thread is attached, it has no JNIEnv, and cannot make JNI calls.
* Attaching a natively-created thread causes a java.lang.Thread object to
* be constructed and added to the "main" ThreadGroup, making it visible to
* the debugger. Calling AttachCurrentThread on an already-attached thread
* is a no-op.
*/
JNIEnv *env = pthread_getspecific(gJVMThreadKey);
if(!env)
{
int status = JCALL(gJavaVM,AttachCurrentThread)(&env, NULL);
if(status < 0)
{
ERR("Failed to attach current thread\n");
return NULL;
}
pthread_setspecific(gJVMThreadKey, env);
}
return env;
}
/* Automatically called by JNI. */
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void* UNUSED(reserved))
{
void *env;
int err;
gJavaVM = jvm;
if(JCALL(gJavaVM,GetEnv)(&env, JNI_VERSION_1_4) != JNI_OK)
{
ERR("Failed to get JNIEnv with JNI_VERSION_1_4\n");
return JNI_ERR;
}
/* Create gJVMThreadKey so we can keep track of the JNIEnv assigned to each
* thread. The JNIEnv *must* be detached before the thread is destroyed.
*/
if((err=pthread_key_create(&gJVMThreadKey, CleanupJNIEnv)) != 0)
ERR("pthread_key_create failed: %d\n", err);
pthread_setspecific(gJVMThreadKey, env);
return JNI_VERSION_1_4;
}
#endif
/************************************************
* Library deinitialization

View File

@ -46,4 +46,12 @@ void CloseLib(void *handle);
void *GetSymbol(void *handle, const char *name);
#endif
#ifdef __ANDROID__
#define JCALL(obj, func) ((*(obj))->func((obj), EXTRACT_VCALL_ARGS
#define JCALL0(obj, func) ((*(obj))->func((obj) EXTRACT_VCALL_ARGS
/** Returns a JNIEnv*. */
void *Android_GetJNIEnv(void);
#endif
#endif /* AL_COMPAT_H */