]> rtime.felk.cvut.cz Git - orte.git/commitdiff
JORTE: prepare for Android (fix class loader problems + add logging)
authorMartin Vajnar <martin.vajnar@gmail.com>
Sun, 7 Jul 2013 16:50:01 +0000 (18:50 +0200)
committerPavel Pisa <pisa@cmp.felk.cvut.cz>
Mon, 23 Sep 2013 09:06:25 +0000 (11:06 +0200)
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.

15 files changed:
orte/include/jorte/4all.h
orte/include/jorte/onLoad.h [new file with mode: 0644]
orte/libjorte/JORTEDomainAppCreate.c
orte/libjorte/JORTEPublicationGetStatus.c
orte/libjorte/JORTEPublicationPropertiesGet.c
orte/libjorte/JORTESubscriptionCreate.c
orte/libjorte/JORTESubscriptionGetStatus.c
orte/libjorte/JORTESubscriptionPropertiesGet.c
orte/libjorte/Makefile.omk
orte/libjorte/createAppInfo.c
orte/libjorte/createPubInfo.c
orte/libjorte/createRecvInfo.c
orte/libjorte/createSubInfo.c
orte/libjorte/onLoad.c [new file with mode: 0644]
orte/libjorte/setRecvInfo.c

index d17624fd1b31bf95721587487570ad52b1b9dcdb..d479ae357a00adfeb93d38f04da42470fb59f11b 100644 (file)
@@ -9,5 +9,16 @@ typedef struct
 } 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
diff --git a/orte/include/jorte/onLoad.h b/orte/include/jorte/onLoad.h
new file mode 100644 (file)
index 0000000..7680239
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef IncludedOnLoad
+#define IncludedOnLoad
+
+#include <jni.h>
+
+jclass findClass(JNIEnv *env, const char* name);
+
+#endif
index 45668b80dbd4177f02031dcbb4114838234e7c72..9ad92063ef34c18a3c3e23d11efebb7da7036c49 100644 (file)
@@ -76,7 +76,7 @@ onRegFail(void *param)
      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
@@ -158,7 +158,7 @@ onMgrNew(const struct ORTEAppInfo *appInfo, void *param)
      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
@@ -250,7 +250,7 @@ onMgrDelete(const struct ORTEAppInfo *appInfo, void *param)
      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
@@ -343,7 +343,7 @@ onAppRemoteNew(const struct ORTEAppInfo *appInfo, void *param)
      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
@@ -436,7 +436,7 @@ onAppDelete(const struct ORTEAppInfo *appInfo, void *param)
      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
@@ -531,7 +531,7 @@ onPubRemoteNew(const struct ORTEAppInfo *appInfo,
      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
@@ -636,7 +636,7 @@ onPubRemoteChanged(const struct ORTEAppInfo *appInfo,
      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
@@ -743,7 +743,7 @@ onPubDelete(const struct ORTEAppInfo *appInfo,
      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
@@ -848,7 +848,7 @@ onSubRemoteNew(const struct ORTEAppInfo *appInfo,
      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
@@ -953,7 +953,7 @@ onSubRemoteChanged(const struct ORTEAppInfo *appInfo,
      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
@@ -1058,7 +1058,7 @@ onSubDelete(const struct ORTEAppInfo *appInfo,
      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
index b96168ced57323e022a248b38565a0217377379f..87892ffe6a01c4d018c981fc3a4468b00b714ba3 100644 (file)
@@ -64,7 +64,7 @@ Java_org_ocera_orte_Publication_jORTEPublicationGetStatus
      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
index 92871067c742049530a53aff7589931f8734c2af..0689013e12305d8ba1188b04c884cbdc4ad208f7 100644 (file)
@@ -71,7 +71,7 @@ Java_org_ocera_orte_Publication_jORTEPublicationPropertiesGet
       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
@@ -158,7 +158,7 @@ Java_org_ocera_orte_Publication_jORTEPublicationPropertiesGet
                             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
index a10a21daff54fb08e35d600a0f037089ecd5ff58..f7dc69c2bca46658ec121c31ecce6b7efaff3f3d 100644 (file)
@@ -116,7 +116,7 @@ recvCallBack(const ORTERecvInfo *info,void *vinstance, void *recvCallBackParam)
     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
index 42302b667edd60e782e7786c053d661d49a02f57..54858209ff47ce183f7c4dd55b7643346c808155 100644 (file)
@@ -65,7 +65,7 @@ Java_org_ocera_orte_Subscription_jORTESubscriptionGetStatus
      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
index 49767e98a0d73ff6b220cfc2c6b8c567edffb99f..73b82e620809183f16ecff3b889cb8972902e2b8 100644 (file)
@@ -68,7 +68,7 @@ Java_org_ocera_orte_Subscription_jORTESubscriptionPropertiesGet
      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
@@ -136,7 +136,7 @@ Java_org_ocera_orte_Subscription_jORTESubscriptionPropertiesGet
                         (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
index fba7c09ac9cbc349378b34eb07e0cb238fabafb5..bb1c0214183ccf07f6cfa48afa1fc7e776365d35 100644 (file)
@@ -15,6 +15,7 @@ lib_LOADLIBES = orte
 INCLUDES = -I $(srcdir)/../include -I $(JAVA_HOME)/include  -I $(JAVA_HOME)/include/linux
 
 jorte_SOURCES = \
+onLoad.c \
 getNtpTime.c \
 setType.c \
 setTopic.c \
index 69f17614f340f8955886f40cf3f7ac79fd5f5f6a..b7771f046d83a416c138536dbd1aed34e01f60d5 100644 (file)
@@ -19,7 +19,7 @@ jobject createAppInfo(JNIEnv *env, const ORTEAppInfo *ainfo)
   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
@@ -183,7 +183,7 @@ jobject createAppInfo(JNIEnv *env, const ORTEAppInfo *ainfo)
                          (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
@@ -238,7 +238,7 @@ jobject createAppInfo(JNIEnv *env, const ORTEAppInfo *ainfo)
                            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
index 3b31a28834fd4a3cb7067d25aa5176eb2a3874a2..16c2ac13b56072e9370136812584a3144aa17d08 100644 (file)
@@ -16,7 +16,7 @@ jobject createPubInfo(JNIEnv *env, const ORTEPubInfo *pinfo)
   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
index 3086b86ff5582808c56a1c1a1c6b706bc1041aa8..8854c8c8d972153330929bc2615c0c3f24d98fcd 100644 (file)
@@ -20,7 +20,7 @@ jobject setRecvInfo(JNIEnv *env, const ORTERecvInfo *rinfo)
   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
@@ -92,7 +92,7 @@ jobject setRecvInfo(JNIEnv *env, const ORTERecvInfo *rinfo)
     }
 /////////////////////////////////////////////////
     // 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
@@ -148,7 +148,7 @@ jobject setRecvInfo(JNIEnv *env, const ORTERecvInfo *rinfo)
                            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
@@ -262,7 +262,7 @@ jobject setRecvInfo(JNIEnv *env, const ORTERecvInfo *rinfo)
                            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
index f87e47818c9deaf700451f1299ff60ba626cc83b..d9190042b7d1e3815f49546808b5eb88153c1d4e 100644 (file)
@@ -17,7 +17,7 @@ jobject createSubInfo(JNIEnv *env, const ORTESubInfo *sinfo)
   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
diff --git a/orte/libjorte/onLoad.c b/orte/libjorte/onLoad.c
new file mode 100644 (file)
index 0000000..f7b8e48
--- /dev/null
@@ -0,0 +1,45 @@
+#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;
+}
index 038ffd9f1a1ca9aad257351548b97f5569dee175..1a783430dffc51f3e2c2c62b43a161d4df097121 100644 (file)
@@ -19,7 +19,7 @@ int setRecvInfo(JNIEnv *env, const ORTERecvInfo *rinfo, jobject obj)
   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
@@ -63,7 +63,7 @@ int setRecvInfo(JNIEnv *env, const ORTERecvInfo *rinfo, jobject obj)
     }
 /////////////////////////////////////////////////
     // 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
@@ -119,7 +119,7 @@ int setRecvInfo(JNIEnv *env, const ORTERecvInfo *rinfo, jobject obj)
                            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
@@ -233,7 +233,7 @@ int setRecvInfo(JNIEnv *env, const ORTERecvInfo *rinfo, jobject obj)
                            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