Browse Source

jclass pointers aren't as cacheable as originally thought.

There is a way to do it.  We can try it later if we determine it's needed for performance reasons.  Otherwise, don't use static to cache them
Grant Limberg 10 years ago
parent
commit
5983b4367b
2 changed files with 278 additions and 494 deletions
  1. 151 270
      java/jni/ZT1_jniutils.cpp
  2. 127 224
      java/jni/com_zerotierone_sdk_Node.cpp

+ 151 - 270
java/jni/ZT1_jniutils.cpp

@@ -6,32 +6,16 @@
 extern "C" {
 #endif
 
-namespace
-{
-    static jclass arrayListClass = NULL;
-    static jmethodID arrayList_constructor = NULL;
-    static jmethodID arrayList_add = NULL;
-
-    static jclass inetAddressClass = NULL;
-    static jmethodID  inetAddress_getByAddress = NULL;
-}
-
 jobject createResultObject(JNIEnv *env, ZT1_ResultCode code)
 {
-    // cache the class so we don't have to
-    // look it up every time we need to create a java
-    // ResultCode object
-    static jclass resultClass = NULL;
+    jclass resultClass = NULL;
     
     jobject resultObject = NULL;
 
+    resultClass = env->FindClass("com/zerotierone/sdk/ResultCode");
     if(resultClass == NULL)
     {
-        resultClass = env->FindClass("com/zerotierone/sdk/ResultCode");
-        if(resultClass == NULL)
-        {
-            return NULL; // exception thrown
-        }
+        return NULL; // exception thrown
     }
 
     std::string fieldName;
@@ -65,8 +49,7 @@ jobject createResultObject(JNIEnv *env, ZT1_ResultCode code)
 
 jobject createVirtualNetworkStatus(JNIEnv *env, ZT1_VirtualNetworkStatus status)
 {
-    static jclass statusClass = NULL;
-    
+    jclass statusClass = NULL;
     jobject statusObject = NULL;
 
     if(statusClass == NULL)
@@ -110,16 +93,13 @@ jobject createVirtualNetworkStatus(JNIEnv *env, ZT1_VirtualNetworkStatus status)
 
 jobject createEvent(JNIEnv *env, ZT1_Event event)
 {
-    static jclass eventClass = NULL;
+    jclass eventClass = NULL;
     jobject eventObject = NULL;
 
+    eventClass = env->FindClass("com/zerotierone/sdk/Event");
     if(eventClass == NULL)
     {
-        eventClass = env->FindClass("com/zerotierone/sdk/Event");
-        if(eventClass == NULL)
-        {
-            return NULL;
-        }
+        return NULL;
     }
 
     std::string fieldName;
@@ -157,16 +137,13 @@ jobject createEvent(JNIEnv *env, ZT1_Event event)
 
 jobject createPeerRole(JNIEnv *env, ZT1_PeerRole role)
 {
-    static jclass peerRoleClass = NULL;
+    jclass peerRoleClass = NULL;
     jobject peerRoleObject = NULL;
 
+    peerRoleClass = env->FindClass("com/zerotierone/sdk/PeerRole");
     if(peerRoleClass == NULL)
     {
-        peerRoleClass = env->FindClass("com/zerotierone/sdk/PeerRole");
-        if(peerRoleClass == NULL)
-        {
-            return NULL;
-        }
+        return NULL;
     }
 
     std::string fieldName;
@@ -192,16 +169,13 @@ jobject createPeerRole(JNIEnv *env, ZT1_PeerRole role)
 
 jobject createVirtualNetworkType(JNIEnv *env, ZT1_VirtualNetworkType type)
 {
-    static jclass vntypeClass = NULL;
+    jclass vntypeClass = NULL;
     jobject vntypeObject = NULL;
 
+    vntypeClass = env->FindClass("com/zerotierone/sdk/VirtualNetworkType");
     if(vntypeClass == NULL)
     {
-        vntypeClass = env->FindClass("com/zerotierone/sdk/VirtualNetworkType");
-        if(vntypeClass == NULL)
-        {
-            return NULL;
-        }
+        return NULL;
     }
 
     std::string fieldName;
@@ -222,16 +196,13 @@ jobject createVirtualNetworkType(JNIEnv *env, ZT1_VirtualNetworkType type)
 
 jobject createVirtualNetworkConfigOperation(JNIEnv *env, ZT1_VirtualNetworkConfigOperation op)
 {
-    static jclass vnetConfigOpClass = NULL;
+    jclass vnetConfigOpClass = NULL;
     jobject vnetConfigOpObject = NULL;
 
+    vnetConfigOpClass = env->FindClass("com/zerotierone/sdk/VirtualNetworkConfigOperation");
     if(vnetConfigOpClass == NULL)
     {
-        vnetConfigOpClass = env->FindClass("com/zerotierone/sdk/VirtualNetworkConfigOperation");
-        if(vnetConfigOpClass == NULL)
-        {
-            return NULL;
-        }
+        return NULL;
     }
 
     std::string fieldName;
@@ -258,23 +229,20 @@ jobject createVirtualNetworkConfigOperation(JNIEnv *env, ZT1_VirtualNetworkConfi
 
 jobject newArrayList(JNIEnv *env)
 {
+    jclass arrayListClass = NULL;
+    jmethodID arrayList_constructor = NULL;
+
+    arrayListClass = env->FindClass("java/util/ArrayList");
     if(arrayListClass == NULL)
     {
-        arrayListClass = env->FindClass("java/util/ArrayList");
-        if(arrayListClass == NULL)
-        {
-            return NULL;
-        }
+        return NULL;
     }
 
+    arrayList_constructor = env->GetMethodID(
+        arrayListClass, "<init>", "()V");
     if(arrayList_constructor == NULL)
     {
-        arrayList_constructor = env->GetMethodID(
-            arrayListClass, "<init>", "()V");
-        if(arrayList_constructor == NULL)
-        {
-            return NULL;
-        }
+        return NULL;
     }
 
     jobject arrayListObj = env->NewObject(arrayListClass, arrayList_constructor);
@@ -287,13 +255,19 @@ bool appendItemToArrayList(JNIEnv *env, jobject array, jobject object)
     assert(array != NULL);
     assert(object != NULL);
 
+    jclass arrayListClass = NULL;
+    jmethodID arrayList_add = NULL;
+
+    arrayListClass = env->FindClass("java/util/ArrayList");
+    if(arrayListClass == NULL)
+    {
+        return NULL;
+    }
+
+    arrayList_add = env->GetMethodID(arrayListClass, "add", "(Ljava.lang.Object;)Z");
     if(arrayList_add == NULL)
     {
-        arrayList_add = env->GetMethodID(arrayListClass, "add", "(Ljava.lang.Object;)Z");
-        if(arrayList_add == NULL)
-        {
-            return false;
-        }
+        return false;
     }
 
     return env->CallBooleanMethod(array, arrayList_add, object);
@@ -301,26 +275,20 @@ bool appendItemToArrayList(JNIEnv *env, jobject array, jobject object)
 
 jobject newInetAddress(JNIEnv *env, const sockaddr_storage &addr)
 {
-    static jclass inetAddressClass = NULL;
-    static jmethodID inetAddress_getByAddress = NULL;
+    jclass inetAddressClass = NULL;
+    jmethodID inetAddress_getByAddress = NULL;
 
+    inetAddressClass = env->FindClass("java/net/InetAddress");
     if(inetAddressClass == NULL)
     {
-        inetAddressClass = env->FindClass("java/net/InetAddress");
-        if(inetAddressClass == NULL)
-        {
-            return NULL;
-        }
+        return NULL;
     }
 
+    inetAddress_getByAddress = env->GetStaticMethodID(
+        inetAddressClass, "getByAddress", "([B)Ljava/net/InetAddress;");
     if(inetAddress_getByAddress == NULL)
     {
-        inetAddress_getByAddress = env->GetStaticMethodID(
-            inetAddressClass, "getByAddress", "([B)Ljava/net/InetAddress;");
-        if(inetAddress_getByAddress == NULL)
-        {
-            return NULL;
-        }
+        return NULL;
     }
 
     jobject inetAddressObj = NULL;
@@ -361,16 +329,13 @@ jobject newInetAddress(JNIEnv *env, const sockaddr_storage &addr)
 
 jobject newInetSocketAddress(JNIEnv *env, const sockaddr_storage &addr)
 {
-    static jclass inetSocketAddressClass = NULL;
-    static jmethodID inetSocketAddress_constructor = NULL;
+    jclass inetSocketAddressClass = NULL;
+    jmethodID inetSocketAddress_constructor = NULL;
 
+    inetSocketAddressClass == env->FindClass("java/net/InetSocketAddress");
     if(inetSocketAddressClass == NULL)
     {
-        inetSocketAddressClass == env->FindClass("java/net/InetSocketAddress");
-        if(inetSocketAddressClass == NULL)
-        {
-            return NULL;
-        }
+        return NULL;
     }
 
     jobject inetAddressObject = newInetAddress(env, addr);
@@ -380,14 +345,11 @@ jobject newInetSocketAddress(JNIEnv *env, const sockaddr_storage &addr)
         return NULL;
     }
 
+    inetSocketAddress_constructor = env->GetMethodID(
+        inetSocketAddressClass, "<init>", "(Ljava/net/InetAddress;I)V");
     if(inetSocketAddress_constructor == NULL)
     {
-        inetSocketAddress_constructor = env->GetMethodID(
-            inetSocketAddressClass, "<init>", "(Ljava/net/InetAddress;I)V");
-        if(inetSocketAddress_constructor == NULL)
-        {
-            return NULL;
-        }
+        return NULL;
     }
 
     int port = 0;
@@ -413,29 +375,23 @@ jobject newInetSocketAddress(JNIEnv *env, const sockaddr_storage &addr)
 
 jobject newMulticastGroup(JNIEnv *env, const ZT1_MulticastGroup &mc)
 {
-    static jclass multicastGroupClass = NULL;
-    static jmethodID multicastGroup_constructor = NULL;
+    jclass multicastGroupClass = NULL;
+    jmethodID multicastGroup_constructor = NULL;
 
-    static jfieldID macField = NULL;
-    static jfieldID adiField = NULL;
+    jfieldID macField = NULL;
+    jfieldID adiField = NULL;
 
+    multicastGroupClass = env->FindClass("com/zerotierone/sdk/MulticastGroup");
     if(multicastGroupClass == NULL)
     {
-        multicastGroupClass = env->FindClass("com/zerotierone/sdk/MulticastGroup");
-        if(multicastGroupClass == NULL)
-        {
-            return NULL;
-        }
+        return NULL;
     }
 
+    multicastGroup_constructor = env->GetMethodID(
+        multicastGroupClass, "<init>", "()V");
     if(multicastGroup_constructor == NULL)
     {
-        multicastGroup_constructor = env->GetMethodID(
-            multicastGroupClass, "<init>", "()V");
-        if(multicastGroup_constructor == NULL)
-        {
-            return NULL;
-        }
+        return NULL;
     }
 
     jobject multicastGroupObj = env->NewObject(multicastGroupClass, multicastGroup_constructor);
@@ -470,87 +426,63 @@ jobject newMulticastGroup(JNIEnv *env, const ZT1_MulticastGroup &mc)
 
 jobject newPeerPhysicalPath(JNIEnv *env, const ZT1_PeerPhysicalPath &ppp)
 {
-    static jclass pppClass = NULL;
+    jclass pppClass = NULL;
 
-    static jfieldID addressField = NULL;
-    static jfieldID lastSendField = NULL;
-    static jfieldID lastReceiveField = NULL;
-    static jfieldID fixedField = NULL;
-    static jfieldID activeField = NULL;
-    static jfieldID preferredField = NULL;
+    jfieldID addressField = NULL;
+    jfieldID lastSendField = NULL;
+    jfieldID lastReceiveField = NULL;
+    jfieldID fixedField = NULL;
+    jfieldID activeField = NULL;
+    jfieldID preferredField = NULL;
 
-    static jmethodID ppp_constructor = NULL;
+    jmethodID ppp_constructor = NULL;
 
+    pppClass = env->FindClass("com/zerotierone/sdk/PeerPhysicalPath");
     if(pppClass == NULL)
     {
-        pppClass = env->FindClass("com/zerotierone/sdk/PeerPhysicalPath");
-        if(pppClass == NULL)
-        {
-            return NULL;
-        }
+        return NULL;
     }
 
+    addressField = env->GetFieldID(pppClass, "address", "Ljava/net/InetAddress;");
     if(addressField == NULL)
     {
-        addressField = env->GetFieldID(pppClass, "address", "Ljava/net/InetAddress;");
-        if(addressField == NULL)
-        {
-            return NULL;
-        }
+        return NULL;
     }
 
+    lastSendField = env->GetFieldID(pppClass, "lastSend", "J");
     if(lastSendField == NULL)
     {
-        lastSendField = env->GetFieldID(pppClass, "lastSend", "J");
-        if(lastSendField == NULL)
-        {
-            return NULL;
-        }
+        return NULL;
     }
 
+    lastReceiveField = env->GetFieldID(pppClass, "lastReceive", "J");
     if(lastReceiveField == NULL)
     {
-        lastReceiveField = env->GetFieldID(pppClass, "lastReceive", "J");
-        if(lastReceiveField == NULL)
-        {
-            return NULL;
-        }
+        return NULL;
     }
 
+    fixedField = env->GetFieldID(pppClass, "fixed", "Z");
     if(fixedField == NULL)
     {
-        fixedField = env->GetFieldID(pppClass, "fixed", "Z");
-        if(fixedField == NULL)
-        {
-            return NULL;
-        }
+        return NULL;
     }
 
+    activeField = env->GetFieldID(pppClass, "active", "Z");
     if(activeField == NULL)
     {
-        activeField = env->GetFieldID(pppClass, "active", "Z");
-        if(activeField == NULL)
-        {
-            return NULL;
-        }
+        return NULL;
     }
 
+    preferredField = env->GetFieldID(pppClass, "preferred", "Z");
     if(preferredField == NULL)
     {
-        preferredField = env->GetFieldID(pppClass, "preferred", "Z");
-        if(preferredField == NULL)
-        {
-            return NULL;
-        }
+        return NULL;
     }
 
+    ppp_constructor = env->GetMethodID(pppClass, "<init>", "()V");
     if(ppp_constructor == NULL)
     {
-        ppp_constructor = env->GetMethodID(pppClass, "<init>", "()V");
-        if(ppp_constructor == NULL)
-        {
-            return NULL;
-        }
+        return NULL;
     }
 
     jobject pppObject = env->NewObject(pppClass, ppp_constructor);
@@ -573,117 +505,84 @@ jobject newPeerPhysicalPath(JNIEnv *env, const ZT1_PeerPhysicalPath &ppp)
 
 jobject newPeer(JNIEnv *env, const ZT1_Peer &peer) 
 {
-    static jclass peerClass = NULL;
+    jclass peerClass = NULL;
 
-    static jfieldID addressField = NULL;
-    static jfieldID lastUnicastFrameField = NULL;
-    static jfieldID lastMulticastFrameField = NULL;
-    static jfieldID versionMajorField = NULL;
-    static jfieldID versionMinorField = NULL;
-    static jfieldID versionRevField = NULL;
-    static jfieldID latencyField = NULL;
-    static jfieldID roleField = NULL;
-    static jfieldID pathsField = NULL;
+    jfieldID addressField = NULL;
+    jfieldID lastUnicastFrameField = NULL;
+    jfieldID lastMulticastFrameField = NULL;
+    jfieldID versionMajorField = NULL;
+    jfieldID versionMinorField = NULL;
+    jfieldID versionRevField = NULL;
+    jfieldID latencyField = NULL;
+    jfieldID roleField = NULL;
+    jfieldID pathsField = NULL;
 
-    static jmethodID peer_constructor = NULL;
+    jmethodID peer_constructor = NULL;
 
+    peerClass = env->FindClass("com/zerotierone/sdk/Peer");
     if(peerClass == NULL)
     {
-        peerClass = env->FindClass("com/zerotierone/sdk/Peer");
-        if(peerClass == NULL)
-        {
-            return NULL;
-        }
+        return NULL;
     }
 
+    addressField = env->GetFieldID(peerClass, "address", "J");
     if(addressField == NULL)
     {
-        addressField = env->GetFieldID(peerClass, "address", "J");
-        if(addressField == NULL)
-        {
-            return NULL;
-        }
+        return NULL;
     }
 
+    lastUnicastFrameField = env->GetFieldID(peerClass, "lastUnicastFrame", "J");
     if(lastUnicastFrameField == NULL)
     {
-        lastUnicastFrameField = env->GetFieldID(peerClass, "lastUnicastFrame", "J");
-        if(lastUnicastFrameField == NULL)
-        {
-            return NULL;
-        }
+        return NULL;
     }
 
+    lastMulticastFrameField = env->GetFieldID(peerClass, "lastMulticastFrame", "J");
     if(lastMulticastFrameField == NULL)
     {
-        lastMulticastFrameField = env->GetFieldID(peerClass, "lastMulticastFrame", "J");
-        if(lastMulticastFrameField == NULL)
-        {
-            return NULL;
-        }
+        return NULL;
     }
 
+    versionMajorField = env->GetFieldID(peerClass, "versionMajor", "I");
     if(versionMajorField == NULL)
     {
-        versionMajorField = env->GetFieldID(peerClass, "versionMajor", "I");
-        if(versionMajorField == NULL)
-        {
-            return NULL;
-        }
+        return NULL;
     }
 
+    versionMinorField = env->GetFieldID(peerClass, "versionMinor", "I");
     if(versionMinorField == NULL)
     {
-        versionMinorField = env->GetFieldID(peerClass, "versionMinor", "I");
-        if(versionMinorField == NULL)
-        {
-            return NULL;
-        }
+        return NULL;
     }
 
+    versionRevField = env->GetFieldID(peerClass, "versionRev", "I");
     if(versionRevField == NULL)
     {
-        versionRevField = env->GetFieldID(peerClass, "versionRev", "I");
-        if(versionRevField == NULL)
-        {
-            return NULL;
-        }
+        return NULL;
     }
 
+    latencyField = env->GetFieldID(peerClass, "latency", "I");
     if(latencyField == NULL)
     {
-        latencyField = env->GetFieldID(peerClass, "latency", "I");
-        if(latencyField == NULL)
-        {
-            return NULL;
-        }
+        return NULL;
     }
 
+    roleField = env->GetFieldID(peerClass, "role", "Lcom/zerotierone/sdk/PeerRole;");
     if(roleField == NULL)
     {
-        roleField = env->GetFieldID(peerClass, "role", "Lcom/zerotierone/sdk/PeerRole;");
-        if(roleField == NULL)
-        {
-            return NULL;
-        }
+        return NULL;
     }
 
+    pathsField = env->GetFieldID(peerClass, "paths", "Ljava.util.ArrayList;");
     if(pathsField == NULL)
     {
-        pathsField = env->GetFieldID(peerClass, "paths", "Ljava.util.ArrayList;");
-        if(pathsField == NULL)
-        {
-            return NULL;
-        }
+        return NULL;
     }
 
+    peer_constructor = env->GetMethodID(peerClass, "<init>", "()V");
     if(peer_constructor == NULL)
     {
-        peer_constructor = env->GetMethodID(peerClass, "<init>", "()V");
-        if(peer_constructor == NULL)
-        {
-            return NULL;
-        }
+        return NULL;
     }
 
     jobject peerObject = env->NewObject(peerClass, peer_constructor);
@@ -715,22 +614,22 @@ jobject newPeer(JNIEnv *env, const ZT1_Peer &peer)
 
 jobject newNetworkConfig(JNIEnv *env, const ZT1_VirtualNetworkConfig &vnetConfig)
 {
-    static jclass vnetConfigClass = NULL;
-    static jmethodID vnetConfig_constructor = NULL;
-    static jfieldID nwidField = NULL;
-    static jfieldID macField = NULL;
-    static jfieldID nameField = NULL;
-    static jfieldID statusField = NULL;
-    static jfieldID typeField = NULL;
-    static jfieldID mtuField = NULL;
-    static jfieldID dhcpField = NULL;
-    static jfieldID bridgeField = NULL;
-    static jfieldID broadcastEnabledField = NULL;
-    static jfieldID portErrorField = NULL;
-    static jfieldID enabledField = NULL;
-    static jfieldID netconfRevisionField = NULL;
-    static jfieldID multicastSubscriptionsField = NULL;
-    static jfieldID assignedAddressesField = NULL;
+    jclass vnetConfigClass = NULL;
+    jmethodID vnetConfig_constructor = NULL;
+    jfieldID nwidField = NULL;
+    jfieldID macField = NULL;
+    jfieldID nameField = NULL;
+    jfieldID statusField = NULL;
+    jfieldID typeField = NULL;
+    jfieldID mtuField = NULL;
+    jfieldID dhcpField = NULL;
+    jfieldID bridgeField = NULL;
+    jfieldID broadcastEnabledField = NULL;
+    jfieldID portErrorField = NULL;
+    jfieldID enabledField = NULL;
+    jfieldID netconfRevisionField = NULL;
+    jfieldID multicastSubscriptionsField = NULL;
+    jfieldID assignedAddressesField = NULL;
 
     if(vnetConfigClass == NULL)
     {
@@ -937,26 +836,20 @@ jobject newNetworkConfig(JNIEnv *env, const ZT1_VirtualNetworkConfig &vnetConfig
 jobject newVersion(JNIEnv *env, int major, int minor, int rev, long featureFlags)
 {
    // create a com.zerotierone.sdk.Version object
-    static jclass versionClass = NULL;
-    static jmethodID versionConstructor = NULL;
+    jclass versionClass = NULL;
+    jmethodID versionConstructor = NULL;
 
+    versionClass = env->FindClass("com/zerotierone/sdk/Version");
     if(versionClass == NULL)
     {
-        versionClass = env->FindClass("com/zerotierone/sdk/Version");
-        if(versionClass == NULL)
-        {
-            return NULL;
-        }
+        return NULL;
     }
 
+    versionConstructor = env->GetMethodID(
+        versionClass, "<init>", "()V");
     if(versionConstructor == NULL)
     {
-        versionConstructor = env->GetMethodID(
-            versionClass, "<init>", "()V");
-        if(versionConstructor == NULL)
-        {
-            return NULL;
-        }
+        return NULL;
     }
 
     jobject versionObj = env->NewObject(versionClass, versionConstructor);
@@ -966,45 +859,33 @@ jobject newVersion(JNIEnv *env, int major, int minor, int rev, long featureFlags
     }
 
     // copy data to Version object
-    static jfieldID majorField = NULL;
-    static jfieldID minorField = NULL;
-    static jfieldID revisionField = NULL;
-    static jfieldID featureFlagsField = NULL;
+    jfieldID majorField = NULL;
+    jfieldID minorField = NULL;
+    jfieldID revisionField = NULL;
+    jfieldID featureFlagsField = NULL;
 
-    if(majorField == NULL)
+    majorField = env->GetFieldID(versionClass, "major", "I");
+    if(majorField = NULL)
     {
-        majorField = env->GetFieldID(versionClass, "major", "I");
-        if(majorField = NULL)
-        {
-            return NULL;
-        }
+        return NULL;
     }
 
+    minorField = env->GetFieldID(versionClass, "minor", "I");
     if(minorField == NULL)
     {
-        minorField = env->GetFieldID(versionClass, "minor", "I");
-        if(minorField == NULL)
-        {
-            return NULL;
-        }
+        return NULL;
     }
 
+    revisionField = env->GetFieldID(versionClass, "revision", "I");
     if(revisionField == NULL)
     {
-        revisionField = env->GetFieldID(versionClass, "revision", "I");
-        if(revisionField == NULL)
-        {
-            return NULL;
-        }
+        return NULL;
     }
 
+    featureFlagsField = env->GetFieldID(versionClass, "featureFlags", "J");
     if(featureFlagsField == NULL)
     {
-        featureFlagsField = env->GetFieldID(versionClass, "featureFlags", "J");
-        if(featureFlagsField == NULL)
-        {
-            return NULL;
-        }
+        return NULL;
     }
 
     env->SetIntField(versionObj, majorField, (jint)major);

+ 127 - 224
java/jni/com_zerotierone_sdk_Node.cpp

@@ -43,64 +43,28 @@ namespace {
     struct JniRef
     {
         JniRef()
-            : env(NULL)
+            : jvm(NULL)
             , node(NULL)
             , dataStoreGetListener(NULL)
-            , dataStoreGetClass(NULL)
-            , dataStoreGetCallbackMethod(NULL)
             , dataStorePutListener(NULL)
-            , dataStorePutClass(NULL)
-            , dataStorePutCallbackMethod(NULL)
-            , deleteMethod(NULL)
             , packetSender(NULL)
-            , packetSenderClass(NULL)
-            , packetSenderCallbackMethod(NULL)
             , eventListener(NULL)
-            , eventListenerClass(NULL)
-            , onEventMethod(NULL)
-            , onOutOfDateMethod(NULL)
-            , onNetworkErrorMethod(NULL)
-            , onTraceMethod(NULL)
             , frameListener(NULL)
-            , frameListenerClass(NULL)
-            , frameListenerCallbackMethod(NULL)
             , configListener(NULL)
-            , configListenerClass(NULL)
-            , configListenerCallbackMethod(NULL)
         {}
+
         uint64_t id;
 
-        JNIEnv *env;
+        JavaVM *jvm;
 
         ZT1_Node *node;
 
         jobject dataStoreGetListener;
-        jclass dataStoreGetClass;
-        jmethodID dataStoreGetCallbackMethod;
-
         jobject dataStorePutListener;
-        jclass dataStorePutClass;
-        jmethodID dataStorePutCallbackMethod;
-        jmethodID deleteMethod;
-
         jobject packetSender;
-        jclass packetSenderClass;
-        jmethodID packetSenderCallbackMethod;
-        
         jobject eventListener;
-        jclass eventListenerClass;
-        jmethodID onEventMethod;
-        jmethodID onOutOfDateMethod;
-        jmethodID onNetworkErrorMethod;
-        jmethodID onTraceMethod;
-
         jobject frameListener;
-        jclass frameListenerClass;
-        jmethodID frameListenerCallbackMethod;
-
         jobject configListener;
-        jclass configListenerClass;
-        jmethodID configListenerCallbackMethod;
     };
 
 
@@ -112,30 +76,23 @@ namespace {
         const ZT1_VirtualNetworkConfig *config)
     {
         JniRef *ref = (JniRef*)userData;
-        assert(ref->node == node);
+        JNIEnv *env = NULL;
+        ref->jvm->GetEnv((void**)&env, JNI_VERSION_1_6);
 
-        JNIEnv *env = ref->env;
-
-        if(ref->configListenerClass == NULL)
+        jclass configListenerClass = env->GetObjectClass(ref->configListener);
+        if(configListenerClass == NULL)
         {
-            ref->configListenerClass = env->GetObjectClass(ref->configListener);
-            if(ref->configListenerClass == NULL)
-            {
-                LOGE("Couldn't find class for VirtualNetworkConfigListener instance");
-                return -1;
-            }
+            LOGE("Couldn't find class for VirtualNetworkConfigListener instance");
+            return -1;
         }
 
-        if(ref->configListenerCallbackMethod == NULL)
+        jmethodID configListenerCallbackMethod = env->GetMethodID(configListenerClass,
+            "onNetworkConfigurationUpdated",
+            "(JLcom/zerotierone/sdk/VirtualNetworkConfigOperation;Lcom/zerotierone/sdk/VirtualNetworkConfig;)I");
+        if(configListenerCallbackMethod == NULL)
         {
-            ref->configListenerCallbackMethod = env->GetMethodID(ref->configListenerClass,
-                "onNetworkConfigurationUpdated",
-                "(JLcom/zerotierone/sdk/VirtualNetworkConfigOperation;Lcom/zerotierone/sdk/VirtualNetworkConfig;)I");
-            if(ref->configListenerCallbackMethod == NULL)
-            {
-                LOGE("Couldn't find onVirtualNetworkFrame() method");
-                return -2;
-            }
+            LOGE("Couldn't find onVirtualNetworkFrame() method");
+            return -2;
         }
 
         jobject operationObject = createVirtualNetworkConfigOperation(env, operation);
@@ -154,7 +111,7 @@ namespace {
 
         return env->CallIntMethod(
             ref->configListener, 
-            ref->configListenerCallbackMethod, 
+            configListenerCallbackMethod, 
             (jlong)nwid, operationObject, networkConfigObject);
     }
 
@@ -169,35 +126,30 @@ namespace {
     {
         JniRef *ref = (JniRef*)userData;
         assert(ref->node == node);
+        JNIEnv *env = NULL;
+        ref->jvm->GetEnv((void**)&env, JNI_VERSION_1_6);
 
-        JNIEnv *env = ref->env;
 
-        if(ref->frameListenerClass == NULL)
+        jclass frameListenerClass = env->GetObjectClass(ref->frameListener);
+        if(frameListenerClass == NULL)
         {
-            ref->frameListenerClass = env->GetObjectClass(ref->frameListener);
-            if(ref->frameListenerClass == NULL)
-            {
-                LOGE("Couldn't find class for VirtualNetworkFrameListener instance");
-                return;
-            }
+            LOGE("Couldn't find class for VirtualNetworkFrameListener instance");
+            return;
         }
 
-        if(ref->frameListenerCallbackMethod == NULL)
+        jmethodID frameListenerCallbackMethod = env->GetMethodID(
+            frameListenerClass,
+            "onVirtualNetworkFrame", "(JJJJJ[B)V");
+        if(frameListenerCallbackMethod == NULL)
         {
-            ref->frameListenerCallbackMethod = env->GetMethodID(
-                ref->frameListenerClass,
-                "onVirtualNetworkFrame", "(JJJJJ[B)V");
-            if(ref->frameListenerCallbackMethod == NULL)
-            {
-                LOGE("Couldn't find onVirtualNetworkFrame() method");
-                return;
-            }
+            LOGE("Couldn't find onVirtualNetworkFrame() method");
+            return;
         }
 
         jbyteArray dataArray = env->NewByteArray(frameLength);
         env->SetByteArrayRegion(dataArray, 0, frameLength, (jbyte*)frameData);
 
-        env->CallVoidMethod(ref->frameListener, ref->frameListenerCallbackMethod, nwid, sourceMac, destMac, etherType, vlanid, dataArray);
+        env->CallVoidMethod(ref->frameListener, frameListenerCallbackMethod, nwid, sourceMac, destMac, etherType, vlanid, dataArray);
     }
 
 
@@ -205,64 +157,50 @@ namespace {
     {
         JniRef *ref = (JniRef*)userData;
         assert(ref->node == node);
+        JNIEnv *env = NULL;
+        ref->jvm->GetEnv((void**)&env, JNI_VERSION_1_6);
 
-        JNIEnv *env = ref->env;
 
-        if(ref->eventListenerClass == NULL)
+        jclass eventListenerClass = env->GetObjectClass(ref->eventListener);
+        if(eventListenerClass == NULL)
         {
-            ref->eventListenerClass = env->GetObjectClass(ref->eventListener);
-            if(ref->eventListenerClass == NULL)
-            {
-                LOGE("Couldn't class for EventListener instance");
-                return;
-            }
+            LOGE("Couldn't class for EventListener instance");
+            return;
         }
 
-        if(ref->onEventMethod == NULL)
+        jmethodID onEventMethod = env->GetMethodID(eventListenerClass,
+            "onEvent", "(Lcom/zerotierone/sdk/Event;)V");
+        if(onEventMethod == NULL)
         {
-            ref->onEventMethod = env->GetMethodID(ref->eventListenerClass,
-                "onEvent", "(Lcom/zerotierone/sdk/Event;)V");
-            if(ref->onEventMethod == NULL)
-            {
-                LOGE("Couldn't find onEvent method");
-                return;
-            }
+            LOGE("Couldn't find onEvent method");
+            return;
         }
 
 
-        if(ref->onOutOfDateMethod == NULL)
+        jmethodID onOutOfDateMethod = env->GetMethodID(eventListenerClass,
+            "onOutOfDate", "(Lcom/zerotierone/sdk/Version;)V");
+        if(onOutOfDateMethod == NULL)
         {
-            ref->onOutOfDateMethod = env->GetMethodID(ref->eventListenerClass,
-                "onOutOfDate", "(Lcom/zerotierone/sdk/Version;)V");
-            if(ref->onOutOfDateMethod == NULL)
-            {
-                LOGE("Couldn't find onOutOfDate method");
-                return;
-            }
+            LOGE("Couldn't find onOutOfDate method");
+            return;
         }
 
 
-        if(ref->onOutOfDateMethod == NULL)
+        jmethodID onNetworkErrorMethod = env->GetMethodID(eventListenerClass,
+            "onNetworkError", "(Lcom/zerotierone/sdk/Event;Ljava/net/InetSocketAddress;)V");
+        if(onNetworkErrorMethod == NULL)
         {
-            ref->onNetworkErrorMethod = env->GetMethodID(ref->eventListenerClass,
-                "onNetworkError", "(Lcom/zerotierone/sdk/Event;Ljava/net/InetSocketAddress;)V");
-            if(ref->onNetworkErrorMethod == NULL)
-            {
-                LOGE("Couldn't find onNetworkError method");
-                return;
-            }
+            LOGE("Couldn't find onNetworkError method");
+            return;
         }
 
 
-        if(ref->onTraceMethod == NULL)
+        jmethodID onTraceMethod = env->GetMethodID(eventListenerClass,
+            "onTrace", "(Ljava/lang/String;)V");
+        if(onTraceMethod == NULL)
         {
-            ref->onTraceMethod = env->GetMethodID(ref->eventListenerClass,
-                "onTrace", "(Ljava/lang/String;)V");
-            if(ref->onTraceMethod == NULL)
-            {
-                LOGE("Couldn't find onTrace method");
-                return;
-            }
+            LOGE("Couldn't find onTrace method");
+            return;
         }
 
         jobject eventObject = createEvent(env, event);
@@ -280,7 +218,7 @@ namespace {
         case ZT1_EVENT_FATAL_ERROR_IDENTITY_COLLISION:
         {
             // call onEvent()
-            env->CallVoidMethod(ref->eventListener, ref->onEventMethod, eventObject);
+            env->CallVoidMethod(ref->eventListener, onEventMethod, eventObject);
         }
         break;
         case ZT1_EVENT_SAW_MORE_RECENT_VERSION:
@@ -290,7 +228,7 @@ namespace {
             {
                 int *version = (int*)data;
                 jobject verisonObj = newVersion(env, version[0], version[1], version[2], 0);
-                env->CallVoidMethod(ref->eventListener, ref->onOutOfDateMethod, verisonObj);
+                env->CallVoidMethod(ref->eventListener, onOutOfDateMethod, verisonObj);
             }
         }
         break;
@@ -302,7 +240,7 @@ namespace {
             {
                 sockaddr_storage *addr = (sockaddr_storage*)data;
                 jobject addressObj = newInetSocketAddress(env, *addr);
-                env->CallVoidMethod(ref->eventListener, ref->onNetworkErrorMethod, addressObj);
+                env->CallVoidMethod(ref->eventListener, onNetworkErrorMethod, addressObj);
             }
         }
         case ZT1_EVENT_TRACE:
@@ -312,7 +250,7 @@ namespace {
             {
                 const char* message = (const char*)data;
                 jstring messageStr = env->NewStringUTF(message);
-                env->CallVoidMethod(ref->eventListener, ref->onTraceMethod);
+                env->CallVoidMethod(ref->eventListener, onTraceMethod);
             }
         }
         break;
@@ -327,29 +265,24 @@ namespace {
         unsigned long *out_objectSize)
     {
         JniRef *ref = (JniRef*)userData;
-        JNIEnv *env = ref->env;
+        JNIEnv *env = NULL;
+        ref->jvm->GetEnv((void**)&env, JNI_VERSION_1_6);
 
-        if(ref->dataStoreGetClass == NULL)
+        jclass dataStoreGetClass = env->GetObjectClass(ref->dataStoreGetListener);
+        if(dataStoreGetClass == NULL)
         {
-            ref->dataStoreGetClass = env->GetObjectClass(ref->dataStoreGetListener);
-            if(ref->dataStoreGetClass == NULL)
-            {
-                LOGE("Couldn't find class for DataStoreGetListener instance");
-                return -1;
-            }
+            LOGE("Couldn't find class for DataStoreGetListener instance");
+            return -1;
         }
 
-        if(ref->dataStoreGetCallbackMethod == NULL)
+        jmethodID dataStoreGetCallbackMethod = env->GetMethodID(
+            dataStoreGetClass,
+            "onDataStoreGet",
+            "(Ljava/lang/String;[BJ[J)J");
+        if(dataStoreGetCallbackMethod == NULL)
         {
-            ref->dataStoreGetCallbackMethod = env->GetMethodID(
-                ref->dataStoreGetClass,
-                "onDataStoreGet",
-                "(Ljava/lang/String;[BJ[J)J");
-            if(ref->dataStoreGetCallbackMethod == NULL)
-            {
-                LOGE("Couldn't find onDataStoreGet method");
-                return -2;
-            }
+            LOGE("Couldn't find onDataStoreGet method");
+            return -2;
         }
 
         jstring nameStr = env->NewStringUTF(objectName);
@@ -363,7 +296,7 @@ namespace {
         jlongArray objectSizeObj = env->NewLongArray(1);
 
         long retval = env->CallLongMethod(
-            ref->dataStoreGetListener, ref->dataStoreGetCallbackMethod, 
+            ref->dataStoreGetListener, dataStoreGetCallbackMethod, 
             nameStr, bufferObj, bufferIndex, objectSizeObj);
 
         env->GetByteArrayRegion(bufferObj, 0, bufferSize, (jbyte*)buffer);
@@ -381,40 +314,33 @@ namespace {
         int secure)
     {
         JniRef *ref = (JniRef*)userData;
-        JNIEnv *env = ref->env;
+        JNIEnv *env = NULL;
+        ref->jvm->GetEnv((void**)&env, JNI_VERSION_1_6);
 
-        if(ref->dataStorePutClass == NULL)
+
+        jclass dataStorePutClass = env->GetObjectClass(ref->dataStorePutListener);
+        if(dataStorePutClass == NULL)
         {
-            ref->dataStorePutClass = env->GetObjectClass(ref->dataStorePutListener);
-            if(ref->dataStorePutClass == NULL)
-            {
-                LOGE("Couldn't find class for DataStorePutListener instance");
-                return -1;
-            }
+            LOGE("Couldn't find class for DataStorePutListener instance");
+            return -1;
         }
 
-        if(ref->dataStorePutCallbackMethod == NULL)
+        jmethodID dataStorePutCallbackMethod = env->GetMethodID(
+            dataStorePutClass,
+            "onDataStorePut",
+            "(Ljava/lang/String;[BZ)I");
+        if(dataStorePutCallbackMethod == NULL)
         {
-            ref->dataStorePutCallbackMethod = env->GetMethodID(
-                ref->dataStorePutClass,
-                "onDataStorePut",
-                "(Ljava/lang/String;[BZ)I");
-            if(ref->dataStorePutCallbackMethod == NULL)
-            {
-                LOGE("Couldn't find onDataStorePut method");
-                return -2;
-            }
+            LOGE("Couldn't find onDataStorePut method");
+            return -2;
         }
 
-        if(ref->deleteMethod == NULL)
+        jmethodID deleteMethod = env->GetMethodID(dataStorePutClass,
+            "onDelete", "(Ljava/lang/String;)I");
+        if(deleteMethod == NULL)
         {
-            ref->deleteMethod = env->GetMethodID(ref->dataStorePutClass,
-                "onDelete", "(Ljava/lang/String;)I");
-            if(ref->deleteMethod == NULL)
-            {
-                LOGE("Couldn't find onDelete method");
-                return -3;
-            }
+            LOGE("Couldn't find onDelete method");
+            return -3;
         }
 
         jstring nameStr = env->NewStringUTF(objectName);
@@ -423,7 +349,7 @@ namespace {
         {
             // delete operation
             return env->CallIntMethod(
-                ref->dataStorePutListener, ref->deleteMethod, nameStr);
+                ref->dataStorePutListener, deleteMethod, nameStr);
         }
         else
         {
@@ -434,7 +360,7 @@ namespace {
 
 
             return env->CallIntMethod(ref->dataStorePutListener,
-                ref->dataStorePutCallbackMethod,
+                dataStorePutCallbackMethod,
                 nameStr, bufferObj, secure);
         }
     }
@@ -448,33 +374,29 @@ namespace {
         JniRef *ref = (JniRef*)userData;
         assert(ref->node == node);
 
-        JNIEnv *env = ref->env;
+        JNIEnv *env = NULL;
+        ref->jvm->GetEnv((void**)&env, JNI_VERSION_1_6);
 
-        if(ref->packetSenderClass == NULL)
+
+        jclass packetSenderClass = env->GetObjectClass(ref->packetSender);
+        if(packetSenderClass == NULL)
         {
-            ref->packetSenderClass = env->GetObjectClass(ref->packetSender);
-            if(ref->packetSenderClass == NULL)
-            {
-                LOGE("Couldn't find class for PacketSender instance");
-                return -1;
-            }
+            LOGE("Couldn't find class for PacketSender instance");
+            return -1;
         }
 
-        if(ref->packetSenderCallbackMethod == NULL)
+        jmethodID packetSenderCallbackMethod = env->GetMethodID(packetSenderClass,
+            "onSendPacketRequested", "(Ljava/net/InetSocketAddress;I[B)I");
+        if(packetSenderCallbackMethod == NULL)
         {
-            ref->packetSenderCallbackMethod = env->GetMethodID(ref->packetSenderClass,
-                "onSendPacketRequested", "(Ljava/net/InetSocketAddress;I[B)I");
-            if(ref->packetSenderCallbackMethod == NULL)
-            {
-                LOGE("Couldn't find onSendPacketRequested method");
-                return -2;
-            }
+            LOGE("Couldn't find onSendPacketRequested method");
+            return -2;
         }
         
         jobject addressObj = newInetSocketAddress(env, *address);
         jbyteArray bufferObj = env->NewByteArray(bufferSize);
         env->SetByteArrayRegion(bufferObj, 0, bufferSize, (jbyte*)buffer);
-        return env->CallIntMethod(ref->packetSender, ref->packetSenderCallbackMethod, addressObj, linkDesparation, bufferObj);
+        return env->CallIntMethod(ref->packetSender, packetSenderCallbackMethod, addressObj, linkDesparation, bufferObj);
     }
 
     typedef std::map<uint64_t, JniRef*> NodeMap;
@@ -506,7 +428,7 @@ JNIEXPORT jobject JNICALL Java_com_zerotierone_sdk_Node_node_1init(
     ZT1_Node *node;
     JniRef *ref = new JniRef;
     ref->id = (uint64_t)now;
-    ref->env = env;
+    env->GetJavaVM(&ref->jvm);
 
     jclass cls = env->GetObjectClass(obj);
     jfieldID fid = env->GetFieldID(
@@ -1019,28 +941,21 @@ JNIEXPORT jobject JNICALL Java_com_zerotierone_sdk_Node_status
         return 0;
     }
 
-    // static so we only have to look these up once
-    static jclass nodeStatusClass = NULL;
-    static jmethodID nodeStatusConstructor = NULL;
+    jclass nodeStatusClass = NULL;
+    jmethodID nodeStatusConstructor = NULL;
 
     // create a com.zerotierone.sdk.NodeStatus object
+    nodeStatusClass = env->FindClass("com/zerotierone/sdk/NodeStatus");
     if(nodeStatusClass == NULL)
     {
-        nodeStatusClass = env->FindClass("com/zerotierone/sdk/NodeStatus");
-        if(nodeStatusClass == NULL)
-        {
-            return NULL;
-        }
+        return NULL;
     }
     
+    nodeStatusConstructor = env->GetMethodID(
+        nodeStatusClass, "<init>", "()V");
     if(nodeStatusConstructor == NULL)
     {
-        nodeStatusConstructor = env->GetMethodID(
-            nodeStatusClass, "<init>", "()V");
-        if(nodeStatusConstructor == NULL)
-        {
-            return NULL;
-        }
+        return NULL;
     }
 
     jobject nodeStatusObj = env->NewObject(nodeStatusClass, nodeStatusConstructor);
@@ -1052,45 +967,33 @@ JNIEXPORT jobject JNICALL Java_com_zerotierone_sdk_Node_status
     ZT1_NodeStatus nodeStatus;
     ZT1_Node_status(node, &nodeStatus);
 
-    static jfieldID addressField = NULL;
-    static jfieldID publicIdentityField = NULL;
-    static jfieldID secretIdentityField = NULL;
-    static jfieldID onlineField = NULL;
+    jfieldID addressField = NULL;
+    jfieldID publicIdentityField = NULL;
+    jfieldID secretIdentityField = NULL;
+    jfieldID onlineField = NULL;
 
+    addressField = env->GetFieldID(nodeStatusClass, "address", "J");
     if(addressField == NULL)
     {
-        addressField = env->GetFieldID(nodeStatusClass, "address", "J");
-        if(addressField == NULL)
-        {
-            return NULL;
-        }
+        return NULL;
     }
 
+    publicIdentityField = env->GetFieldID(nodeStatusClass, "publicIdentity", "Ljava/lang/String;");
     if(publicIdentityField == NULL)
     {
-        publicIdentityField = env->GetFieldID(nodeStatusClass, "publicIdentity", "Ljava/lang/String;");
-        if(publicIdentityField == NULL)
-        {
-            return NULL;
-        }
+        return NULL;
     }
 
+    secretIdentityField = env->GetFieldID(nodeStatusClass, "secretIdentity", "Ljava/lang/String;");
     if(secretIdentityField == NULL)
     {
-        secretIdentityField = env->GetFieldID(nodeStatusClass, "secretIdentity", "Ljava/lang/String;");
-        if(secretIdentityField == NULL)
-        {
-            return NULL;
-        }
+        return NULL;
     }
 
+    onlineField = env->GetFieldID(nodeStatusClass, "online", "Z");
     if(onlineField == NULL)
     {
-        onlineField = env->GetFieldID(nodeStatusClass, "online", "Z");
-        if(onlineField == NULL)
-        {
-            return NULL;
-        }
+        return NULL;
     }
 
     env->SetLongField(nodeStatusObj, addressField, nodeStatus.address);