This fixes class loading problems on Android.
As per the Android Documentation (http://developer.android.com/training/articles/perf-jni.html#faq_FindClass):
Android's Dalvik VM uses the loader associated with the method
at the top of the interpreted stack, or if there isn't one
(because the thread was just attached), it uses the "system" class
loader, for FindClass calls.
To overcome this the JNI_OnLoad function is used. Any FindClass calls made
from there will happen in the context of the class loader used to load
the shared library. So from there one class that will always be present
in the JORTE Java package is chosen (org.ocera.orte.JOrte) and it's
class loader is stored as a global reference inside the VM (thus shared
by all processes attached to the VM) and as a static variable (accesible
only by functions from the onLoad.c file) on the C side.Also the findClass
and findLoadedClass method IDs are cached. To simplify the class loading
process inside C functions the findClass functions is written.
Android also doesn't implement the printf function. However it does have
a logging capability, so a variadic macro replacing occurences of printf
with __android_log_print is used.
} JORTECallbackContext_t;
*/
// pro test purposes only
-//#define TEST_STAGE
+#ifndef Included4all
+#define Included4all
+#define TEST_STAGE
+
+#include "onLoad.h"
+#ifdef __ANDROID__
+
+#include <android/log.h>
+#define printf(...) __android_log_print(ANDROID_LOG_INFO, "ORTE", __VA_ARGS__)
+
+#endif
+#endif
--- /dev/null
+#ifndef IncludedOnLoad
+#define IncludedOnLoad
+
+#include <jni.h>
+
+jclass findClass(JNIEnv *env, const char* name);
+
+#endif
break;
}
// find class
- cls = (*env)->FindClass(env, "org/ocera/orte/types/DomainEvents");
+ cls = findClass(env, "org.ocera.orte.types.DomainEvents");
if(cls == 0)
{
#ifdef TEST_STAGE
break;
}
// find class
- cls = (*env)->FindClass(env, "org/ocera/orte/types/DomainEvents");
+ cls = findClass(env, "org.ocera.orte.types.DomainEvents");
if(cls == 0)
{
#ifdef TEST_STAGE
break;
}
// find class
- cls = (*env)->FindClass(env, "org/ocera/orte/types/DomainEvents");
+ cls = findClass(env, "org.ocera.orte.types.DomainEvents");
if(cls == 0)
{
#ifdef TEST_STAGE
break;
}
// find class
- cls = (*env)->FindClass(env, "org/ocera/orte/types/DomainEvents");
+ cls = findClass(env, "org.ocera.orte.types.DomainEvents");
if(cls == 0)
{
#ifdef TEST_STAGE
break;
}
// find class
- cls = (*env)->FindClass(env, "org/ocera/orte/types/DomainEvents");
+ cls = findClass(env, "org.ocera.orte.types.DomainEvents");
if(cls == 0)
{
#ifdef TEST_STAGE
break;
}
// find class
- cls = (*env)->FindClass(env, "org/ocera/orte/types/DomainEvents");
+ cls = findClass(env, "org.ocera.orte.types.DomainEvents");
if(cls == 0)
{
#ifdef TEST_STAGE
break;
}
// find class
- cls = (*env)->FindClass(env, "org/ocera/orte/types/DomainEvents");
+ cls = findClass(env, "org.ocera.orte.types.DomainEvents");
if(cls == 0)
{
#ifdef TEST_STAGE
break;
}
// find class
- cls = (*env)->FindClass(env, "org/ocera/orte/types/DomainEvents");
+ cls = findClass(env, "org.ocera.orte.types.DomainEvents");
if(cls == 0)
{
#ifdef TEST_STAGE
break;
}
// find class
- cls = (*env)->FindClass(env, "org/ocera/orte/types/DomainEvents");
+ cls = findClass(env, "org.ocera.orte.types.DomainEvents");
if(cls == 0)
{
#ifdef TEST_STAGE
break;
}
// find class
- cls = (*env)->FindClass(env, "org/ocera/orte/types/DomainEvents");
+ cls = findClass(env, "org.ocera.orte.types.DomainEvents");
if(cls == 0)
{
#ifdef TEST_STAGE
break;
}
// find class
- cls = (*env)->FindClass(env, "org/ocera/orte/types/DomainEvents");
+ cls = findClass(env, "org.ocera.orte.types.DomainEvents");
if(cls == 0)
{
#ifdef TEST_STAGE
break;
}
// find cls
- cls_ps = (*env)->FindClass(env,"org/ocera/orte/types/Status");
+ cls_ps = findClass(env,"org.ocera.orte.types.Status");
if(cls_ps == 0)
{
#ifdef TEST_STAGE
break;
}
// find class
- cls_pp = (*env)->FindClass(env, "org/ocera/orte/types/PublProp");
+ cls_pp = findClass(env, "org.ocera.orte.types.PublProp");
if(cls_pp == 0)
{
#ifdef TEST_STAGE
jbool);
/////////////////////////////////////////////////
// fieldID - persistence
- cls_ntpT = (*env)->FindClass(env, "org/ocera/orte/types/NtpTime");
+ cls_ntpT = findClass(env, "org.ocera.orte.types.NtpTime");
if(cls_ntpT == 0)
{
#ifdef TEST_STAGE
if(rinfo == 0)
{
// find cls
- cls = (*env)->FindClass(env, "org/ocera/orte/types/RecvInfo");
+ cls = findClass(env, "org.ocera.orte.types.RecvInfo");
if(cls == 0)
{
#ifdef TEST_STAGE
break;
}
// find cls
- cls_ss = (*env)->FindClass(env,"org/ocera/orte/types/Status");
+ cls_ss = findClass(env,"org.ocera.orte.types.Status");
if(cls_ss == 0)
{
#ifdef TEST_STAGE
break;
}
// get cls
- cls_sp = (*env)->FindClass(env, "org/ocera/orte/types/SubsProp");
+ cls_sp = findClass(env, "org.ocera.orte.types.SubsProp");
if(cls_sp == 0)
{
#ifdef TEST_STAGE
(jint) subs_prop->typeChecksum);
/////////////////////////////////////////////////
// fieldID - minSeparation
- cls_ntpT = (*env)->FindClass(env, "org/ocera/orte/types/NtpTime");
+ cls_ntpT = findClass(env, "org.ocera.orte.types.NtpTime");
if(cls_ntpT == 0)
{
#ifdef TEST_STAGE
INCLUDES = -I $(srcdir)/../include -I $(JAVA_HOME)/include -I $(JAVA_HOME)/include/linux
jorte_SOURCES = \
+onLoad.c \
getNtpTime.c \
setType.c \
setTopic.c \
do
{
// find cls
- cls = (*env)->FindClass(env, "org/ocera/orte/types/AppInfo");
+ cls = findClass(env, "org.ocera.orte.types.AppInfo");
if(cls == 0)
{
#ifdef TEST_STAGE
(jlong) ainfo->userdataUnicastPort);
// find cls - VendorID
- cls_tmp = (*env)->FindClass(env, "org/ocera/orte/types/VendorId");
+ cls_tmp = findClass(env, "org.ocera.orte.types.VendorId");
if(cls_tmp == 0)
{
#ifdef TEST_STAGE
obj_tmp);
// find cls - VendorID
- cls_tmp = (*env)->FindClass(env, "org/ocera/orte/types/ProtocolVersion");
+ cls_tmp = findClass(env, "org.ocera.orte.types.ProtocolVersion");
if(cls_tmp == 0)
{
#ifdef TEST_STAGE
do
{
// find cls
- cls = (*env)->FindClass(env, "org/ocera/orte/types/PubInfo");
+ cls = findClass(env, "org.ocera.orte.types.PubInfo");
if(cls == 0)
{
#ifdef TEST_STAGE
do
{
// find cls
- cls = (*env)->FindClass(env, "org/ocera/orte/types/RecvInfo");
+ cls = findClass(env, "org.ocera.orte.types.RecvInfo");
if(cls == 0)
{
#ifdef TEST_STAGE
}
/////////////////////////////////////////////////
// find cls - GUID_RTPS
- cls_tmp = (*env)->FindClass(env, "org/ocera/orte/types/GUID_RTPS");
+ cls_tmp = findClass(env, "org.ocera.orte.types.GUID_RTPS");
if(cls_tmp == 0)
{
#ifdef TEST_STAGE
obj_tmp);
/////////////////////////////////////////////////
// find cls - NtpTime
- cls_tmp = (*env)->FindClass(env, "org/ocera/orte/types/NtpTime");
+ cls_tmp = findClass(env, "org.ocera.orte.types.NtpTime");
if(cls_tmp == 0)
{
#ifdef TEST_STAGE
obj_tmp);
/////////////////////////////////////////////////
// find cls - SequenceNumber
- cls_tmp = (*env)->FindClass(env,"org/ocera/orte/types/SequenceNumber");
+ cls_tmp = findClass(env,"org.ocera.orte.types.SequenceNumber");
if(cls_tmp == 0)
{
#ifdef TEST_STAGE
do
{
// find cls
- cls = (*env)->FindClass(env, "org/ocera/orte/types/SubInfo");
+ cls = findClass(env, "org.ocera.orte.types.SubInfo");
if(cls == 0)
{
#ifdef TEST_STAGE
--- /dev/null
+#include <stdlib.h>
+#include <jni.h>
+
+static jmethodID findClassM;
+static jmethodID findLoadedClassM;
+static jobject classLoader;
+
+JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
+ JNIEnv *env;
+ jclass testCl;
+ jclass clClass;
+ jclass clClassLoader;
+ jmethodID getClassLoader;
+
+ (*vm)->GetEnv(vm, (void **)&env, JNI_VERSION_1_6);
+
+ testCl = (*env)->FindClass(env, "org/ocera/orte/JOrte");
+ clClass = (*env)->FindClass(env, "java/lang/Class");
+ clClassLoader = (*env)->FindClass(env, "java/lang/ClassLoader");
+ getClassLoader = (*env)->GetMethodID(env, clClass, "getClassLoader", "()Ljava/lang/ClassLoader;");
+ classLoader = (*env)->CallObjectMethod(env, testCl, getClassLoader);
+ classLoader = (*env)->NewGlobalRef(env, classLoader);
+ findClassM = (*env)->GetMethodID(env, clClassLoader, "findClass", "(Ljava/lang/String;)Ljava/lang/Class;");
+ findLoadedClassM = (*env)->GetMethodID(env, clClassLoader, "findLoadedClass", "(Ljava/lang/String;)Ljava/lang/Class;");
+
+ return JNI_VERSION_1_6;
+}
+
+JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved) {
+ JNIEnv *env;
+
+ (*vm)->GetEnv(vm, (void **)&env, JNI_VERSION_1_6);
+
+ (*env)->DeleteGlobalRef(env, classLoader);
+}
+
+jclass findClass(JNIEnv *env, const char* name) {
+ jclass cl;
+
+ if ((cl = (*env)->CallObjectMethod(env, classLoader, findLoadedClassM, (*env)->NewStringUTF(env, name))) == NULL) {
+ cl = (*env)->CallObjectMethod(env, classLoader, findClassM, (*env)->NewStringUTF(env, name));
+ }
+
+ return cl;
+}
do
{
// find cls
- cls = (*env)->FindClass(env, "org/ocera/orte/types/RecvInfo");
+ cls = findClass(env, "org.ocera.orte.types.RecvInfo");
if(cls == 0)
{
#ifdef TEST_STAGE
}
/////////////////////////////////////////////////
// find cls - GUID_RTPS
- cls_tmp = (*env)->FindClass(env, "org/ocera/orte/types/GUID_RTPS");
+ cls_tmp = findClass(env, "org.ocera.orte.types.GUID_RTPS");
if(cls_tmp == 0)
{
#ifdef TEST_STAGE
obj_tmp);
/////////////////////////////////////////////////
// find cls - NtpTime
- cls_tmp = (*env)->FindClass(env, "org/ocera/orte/types/NtpTime");
+ cls_tmp = findClass(env, "org.ocera.orte.types.NtpTime");
if(cls_tmp == 0)
{
#ifdef TEST_STAGE
obj_tmp);
/////////////////////////////////////////////////
// find cls - SequenceNumber
- cls_tmp = (*env)->FindClass(env,"org/ocera/orte/types/SequenceNumber");
+ cls_tmp = findClass(env,"org.ocera.orte.types.SequenceNumber");
if(cls_tmp == 0)
{
#ifdef TEST_STAGE