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" {
 extern "C" {
 #endif
 #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)
 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;
     jobject resultObject = NULL;
 
 
+    resultClass = env->FindClass("com/zerotierone/sdk/ResultCode");
     if(resultClass == NULL)
     if(resultClass == NULL)
     {
     {
-        resultClass = env->FindClass("com/zerotierone/sdk/ResultCode");
-        if(resultClass == NULL)
-        {
-            return NULL; // exception thrown
-        }
+        return NULL; // exception thrown
     }
     }
 
 
     std::string fieldName;
     std::string fieldName;
@@ -65,8 +49,7 @@ jobject createResultObject(JNIEnv *env, ZT1_ResultCode code)
 
 
 jobject createVirtualNetworkStatus(JNIEnv *env, ZT1_VirtualNetworkStatus status)
 jobject createVirtualNetworkStatus(JNIEnv *env, ZT1_VirtualNetworkStatus status)
 {
 {
-    static jclass statusClass = NULL;
-    
+    jclass statusClass = NULL;
     jobject statusObject = NULL;
     jobject statusObject = NULL;
 
 
     if(statusClass == NULL)
     if(statusClass == NULL)
@@ -110,16 +93,13 @@ jobject createVirtualNetworkStatus(JNIEnv *env, ZT1_VirtualNetworkStatus status)
 
 
 jobject createEvent(JNIEnv *env, ZT1_Event event)
 jobject createEvent(JNIEnv *env, ZT1_Event event)
 {
 {
-    static jclass eventClass = NULL;
+    jclass eventClass = NULL;
     jobject eventObject = NULL;
     jobject eventObject = NULL;
 
 
+    eventClass = env->FindClass("com/zerotierone/sdk/Event");
     if(eventClass == NULL)
     if(eventClass == NULL)
     {
     {
-        eventClass = env->FindClass("com/zerotierone/sdk/Event");
-        if(eventClass == NULL)
-        {
-            return NULL;
-        }
+        return NULL;
     }
     }
 
 
     std::string fieldName;
     std::string fieldName;
@@ -157,16 +137,13 @@ jobject createEvent(JNIEnv *env, ZT1_Event event)
 
 
 jobject createPeerRole(JNIEnv *env, ZT1_PeerRole role)
 jobject createPeerRole(JNIEnv *env, ZT1_PeerRole role)
 {
 {
-    static jclass peerRoleClass = NULL;
+    jclass peerRoleClass = NULL;
     jobject peerRoleObject = NULL;
     jobject peerRoleObject = NULL;
 
 
+    peerRoleClass = env->FindClass("com/zerotierone/sdk/PeerRole");
     if(peerRoleClass == NULL)
     if(peerRoleClass == NULL)
     {
     {
-        peerRoleClass = env->FindClass("com/zerotierone/sdk/PeerRole");
-        if(peerRoleClass == NULL)
-        {
-            return NULL;
-        }
+        return NULL;
     }
     }
 
 
     std::string fieldName;
     std::string fieldName;
@@ -192,16 +169,13 @@ jobject createPeerRole(JNIEnv *env, ZT1_PeerRole role)
 
 
 jobject createVirtualNetworkType(JNIEnv *env, ZT1_VirtualNetworkType type)
 jobject createVirtualNetworkType(JNIEnv *env, ZT1_VirtualNetworkType type)
 {
 {
-    static jclass vntypeClass = NULL;
+    jclass vntypeClass = NULL;
     jobject vntypeObject = NULL;
     jobject vntypeObject = NULL;
 
 
+    vntypeClass = env->FindClass("com/zerotierone/sdk/VirtualNetworkType");
     if(vntypeClass == NULL)
     if(vntypeClass == NULL)
     {
     {
-        vntypeClass = env->FindClass("com/zerotierone/sdk/VirtualNetworkType");
-        if(vntypeClass == NULL)
-        {
-            return NULL;
-        }
+        return NULL;
     }
     }
 
 
     std::string fieldName;
     std::string fieldName;
@@ -222,16 +196,13 @@ jobject createVirtualNetworkType(JNIEnv *env, ZT1_VirtualNetworkType type)
 
 
 jobject createVirtualNetworkConfigOperation(JNIEnv *env, ZT1_VirtualNetworkConfigOperation op)
 jobject createVirtualNetworkConfigOperation(JNIEnv *env, ZT1_VirtualNetworkConfigOperation op)
 {
 {
-    static jclass vnetConfigOpClass = NULL;
+    jclass vnetConfigOpClass = NULL;
     jobject vnetConfigOpObject = NULL;
     jobject vnetConfigOpObject = NULL;
 
 
+    vnetConfigOpClass = env->FindClass("com/zerotierone/sdk/VirtualNetworkConfigOperation");
     if(vnetConfigOpClass == NULL)
     if(vnetConfigOpClass == NULL)
     {
     {
-        vnetConfigOpClass = env->FindClass("com/zerotierone/sdk/VirtualNetworkConfigOperation");
-        if(vnetConfigOpClass == NULL)
-        {
-            return NULL;
-        }
+        return NULL;
     }
     }
 
 
     std::string fieldName;
     std::string fieldName;
@@ -258,23 +229,20 @@ jobject createVirtualNetworkConfigOperation(JNIEnv *env, ZT1_VirtualNetworkConfi
 
 
 jobject newArrayList(JNIEnv *env)
 jobject newArrayList(JNIEnv *env)
 {
 {
+    jclass arrayListClass = NULL;
+    jmethodID arrayList_constructor = NULL;
+
+    arrayListClass = env->FindClass("java/util/ArrayList");
     if(arrayListClass == NULL)
     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)
     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);
     jobject arrayListObj = env->NewObject(arrayListClass, arrayList_constructor);
@@ -287,13 +255,19 @@ bool appendItemToArrayList(JNIEnv *env, jobject array, jobject object)
     assert(array != NULL);
     assert(array != NULL);
     assert(object != 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)
     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);
     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)
 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)
     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)
     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;
     jobject inetAddressObj = NULL;
@@ -361,16 +329,13 @@ jobject newInetAddress(JNIEnv *env, const sockaddr_storage &addr)
 
 
 jobject newInetSocketAddress(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)
     if(inetSocketAddressClass == NULL)
     {
     {
-        inetSocketAddressClass == env->FindClass("java/net/InetSocketAddress");
-        if(inetSocketAddressClass == NULL)
-        {
-            return NULL;
-        }
+        return NULL;
     }
     }
 
 
     jobject inetAddressObject = newInetAddress(env, addr);
     jobject inetAddressObject = newInetAddress(env, addr);
@@ -380,14 +345,11 @@ jobject newInetSocketAddress(JNIEnv *env, const sockaddr_storage &addr)
         return NULL;
         return NULL;
     }
     }
 
 
+    inetSocketAddress_constructor = env->GetMethodID(
+        inetSocketAddressClass, "<init>", "(Ljava/net/InetAddress;I)V");
     if(inetSocketAddress_constructor == NULL)
     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;
     int port = 0;
@@ -413,29 +375,23 @@ jobject newInetSocketAddress(JNIEnv *env, const sockaddr_storage &addr)
 
 
 jobject newMulticastGroup(JNIEnv *env, const ZT1_MulticastGroup &mc)
 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)
     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)
     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);
     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)
 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)
     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)
     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)
     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)
     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)
     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)
     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)
     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)
     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);
     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) 
 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)
     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)
     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)
     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)
     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)
     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)
     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)
     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)
     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)
     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)
     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)
     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);
     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)
 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)
     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)
 jobject newVersion(JNIEnv *env, int major, int minor, int rev, long featureFlags)
 {
 {
    // create a com.zerotierone.sdk.Version object
    // 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)
     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)
     if(versionConstructor == NULL)
     {
     {
-        versionConstructor = env->GetMethodID(
-            versionClass, "<init>", "()V");
-        if(versionConstructor == NULL)
-        {
-            return NULL;
-        }
+        return NULL;
     }
     }
 
 
     jobject versionObj = env->NewObject(versionClass, versionConstructor);
     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
     // 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)
     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)
     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)
     if(featureFlagsField == NULL)
     {
     {
-        featureFlagsField = env->GetFieldID(versionClass, "featureFlags", "J");
-        if(featureFlagsField == NULL)
-        {
-            return NULL;
-        }
+        return NULL;
     }
     }
 
 
     env->SetIntField(versionObj, majorField, (jint)major);
     env->SetIntField(versionObj, majorField, (jint)major);

+ 127 - 224
java/jni/com_zerotierone_sdk_Node.cpp

@@ -43,64 +43,28 @@ namespace {
     struct JniRef
     struct JniRef
     {
     {
         JniRef()
         JniRef()
-            : env(NULL)
+            : jvm(NULL)
             , node(NULL)
             , node(NULL)
             , dataStoreGetListener(NULL)
             , dataStoreGetListener(NULL)
-            , dataStoreGetClass(NULL)
-            , dataStoreGetCallbackMethod(NULL)
             , dataStorePutListener(NULL)
             , dataStorePutListener(NULL)
-            , dataStorePutClass(NULL)
-            , dataStorePutCallbackMethod(NULL)
-            , deleteMethod(NULL)
             , packetSender(NULL)
             , packetSender(NULL)
-            , packetSenderClass(NULL)
-            , packetSenderCallbackMethod(NULL)
             , eventListener(NULL)
             , eventListener(NULL)
-            , eventListenerClass(NULL)
-            , onEventMethod(NULL)
-            , onOutOfDateMethod(NULL)
-            , onNetworkErrorMethod(NULL)
-            , onTraceMethod(NULL)
             , frameListener(NULL)
             , frameListener(NULL)
-            , frameListenerClass(NULL)
-            , frameListenerCallbackMethod(NULL)
             , configListener(NULL)
             , configListener(NULL)
-            , configListenerClass(NULL)
-            , configListenerCallbackMethod(NULL)
         {}
         {}
+
         uint64_t id;
         uint64_t id;
 
 
-        JNIEnv *env;
+        JavaVM *jvm;
 
 
         ZT1_Node *node;
         ZT1_Node *node;
 
 
         jobject dataStoreGetListener;
         jobject dataStoreGetListener;
-        jclass dataStoreGetClass;
-        jmethodID dataStoreGetCallbackMethod;
-
         jobject dataStorePutListener;
         jobject dataStorePutListener;
-        jclass dataStorePutClass;
-        jmethodID dataStorePutCallbackMethod;
-        jmethodID deleteMethod;
-
         jobject packetSender;
         jobject packetSender;
-        jclass packetSenderClass;
-        jmethodID packetSenderCallbackMethod;
-        
         jobject eventListener;
         jobject eventListener;
-        jclass eventListenerClass;
-        jmethodID onEventMethod;
-        jmethodID onOutOfDateMethod;
-        jmethodID onNetworkErrorMethod;
-        jmethodID onTraceMethod;
-
         jobject frameListener;
         jobject frameListener;
-        jclass frameListenerClass;
-        jmethodID frameListenerCallbackMethod;
-
         jobject configListener;
         jobject configListener;
-        jclass configListenerClass;
-        jmethodID configListenerCallbackMethod;
     };
     };
 
 
 
 
@@ -112,30 +76,23 @@ namespace {
         const ZT1_VirtualNetworkConfig *config)
         const ZT1_VirtualNetworkConfig *config)
     {
     {
         JniRef *ref = (JniRef*)userData;
         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);
         jobject operationObject = createVirtualNetworkConfigOperation(env, operation);
@@ -154,7 +111,7 @@ namespace {
 
 
         return env->CallIntMethod(
         return env->CallIntMethod(
             ref->configListener, 
             ref->configListener, 
-            ref->configListenerCallbackMethod, 
+            configListenerCallbackMethod, 
             (jlong)nwid, operationObject, networkConfigObject);
             (jlong)nwid, operationObject, networkConfigObject);
     }
     }
 
 
@@ -169,35 +126,30 @@ namespace {
     {
     {
         JniRef *ref = (JniRef*)userData;
         JniRef *ref = (JniRef*)userData;
         assert(ref->node == node);
         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);
         jbyteArray dataArray = env->NewByteArray(frameLength);
         env->SetByteArrayRegion(dataArray, 0, frameLength, (jbyte*)frameData);
         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;
         JniRef *ref = (JniRef*)userData;
         assert(ref->node == node);
         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);
         jobject eventObject = createEvent(env, event);
@@ -280,7 +218,7 @@ namespace {
         case ZT1_EVENT_FATAL_ERROR_IDENTITY_COLLISION:
         case ZT1_EVENT_FATAL_ERROR_IDENTITY_COLLISION:
         {
         {
             // call onEvent()
             // call onEvent()
-            env->CallVoidMethod(ref->eventListener, ref->onEventMethod, eventObject);
+            env->CallVoidMethod(ref->eventListener, onEventMethod, eventObject);
         }
         }
         break;
         break;
         case ZT1_EVENT_SAW_MORE_RECENT_VERSION:
         case ZT1_EVENT_SAW_MORE_RECENT_VERSION:
@@ -290,7 +228,7 @@ namespace {
             {
             {
                 int *version = (int*)data;
                 int *version = (int*)data;
                 jobject verisonObj = newVersion(env, version[0], version[1], version[2], 0);
                 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;
         break;
@@ -302,7 +240,7 @@ namespace {
             {
             {
                 sockaddr_storage *addr = (sockaddr_storage*)data;
                 sockaddr_storage *addr = (sockaddr_storage*)data;
                 jobject addressObj = newInetSocketAddress(env, *addr);
                 jobject addressObj = newInetSocketAddress(env, *addr);
-                env->CallVoidMethod(ref->eventListener, ref->onNetworkErrorMethod, addressObj);
+                env->CallVoidMethod(ref->eventListener, onNetworkErrorMethod, addressObj);
             }
             }
         }
         }
         case ZT1_EVENT_TRACE:
         case ZT1_EVENT_TRACE:
@@ -312,7 +250,7 @@ namespace {
             {
             {
                 const char* message = (const char*)data;
                 const char* message = (const char*)data;
                 jstring messageStr = env->NewStringUTF(message);
                 jstring messageStr = env->NewStringUTF(message);
-                env->CallVoidMethod(ref->eventListener, ref->onTraceMethod);
+                env->CallVoidMethod(ref->eventListener, onTraceMethod);
             }
             }
         }
         }
         break;
         break;
@@ -327,29 +265,24 @@ namespace {
         unsigned long *out_objectSize)
         unsigned long *out_objectSize)
     {
     {
         JniRef *ref = (JniRef*)userData;
         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);
         jstring nameStr = env->NewStringUTF(objectName);
@@ -363,7 +296,7 @@ namespace {
         jlongArray objectSizeObj = env->NewLongArray(1);
         jlongArray objectSizeObj = env->NewLongArray(1);
 
 
         long retval = env->CallLongMethod(
         long retval = env->CallLongMethod(
-            ref->dataStoreGetListener, ref->dataStoreGetCallbackMethod, 
+            ref->dataStoreGetListener, dataStoreGetCallbackMethod, 
             nameStr, bufferObj, bufferIndex, objectSizeObj);
             nameStr, bufferObj, bufferIndex, objectSizeObj);
 
 
         env->GetByteArrayRegion(bufferObj, 0, bufferSize, (jbyte*)buffer);
         env->GetByteArrayRegion(bufferObj, 0, bufferSize, (jbyte*)buffer);
@@ -381,40 +314,33 @@ namespace {
         int secure)
         int secure)
     {
     {
         JniRef *ref = (JniRef*)userData;
         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);
         jstring nameStr = env->NewStringUTF(objectName);
@@ -423,7 +349,7 @@ namespace {
         {
         {
             // delete operation
             // delete operation
             return env->CallIntMethod(
             return env->CallIntMethod(
-                ref->dataStorePutListener, ref->deleteMethod, nameStr);
+                ref->dataStorePutListener, deleteMethod, nameStr);
         }
         }
         else
         else
         {
         {
@@ -434,7 +360,7 @@ namespace {
 
 
 
 
             return env->CallIntMethod(ref->dataStorePutListener,
             return env->CallIntMethod(ref->dataStorePutListener,
-                ref->dataStorePutCallbackMethod,
+                dataStorePutCallbackMethod,
                 nameStr, bufferObj, secure);
                 nameStr, bufferObj, secure);
         }
         }
     }
     }
@@ -448,33 +374,29 @@ namespace {
         JniRef *ref = (JniRef*)userData;
         JniRef *ref = (JniRef*)userData;
         assert(ref->node == node);
         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);
         jobject addressObj = newInetSocketAddress(env, *address);
         jbyteArray bufferObj = env->NewByteArray(bufferSize);
         jbyteArray bufferObj = env->NewByteArray(bufferSize);
         env->SetByteArrayRegion(bufferObj, 0, bufferSize, (jbyte*)buffer);
         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;
     typedef std::map<uint64_t, JniRef*> NodeMap;
@@ -506,7 +428,7 @@ JNIEXPORT jobject JNICALL Java_com_zerotierone_sdk_Node_node_1init(
     ZT1_Node *node;
     ZT1_Node *node;
     JniRef *ref = new JniRef;
     JniRef *ref = new JniRef;
     ref->id = (uint64_t)now;
     ref->id = (uint64_t)now;
-    ref->env = env;
+    env->GetJavaVM(&ref->jvm);
 
 
     jclass cls = env->GetObjectClass(obj);
     jclass cls = env->GetObjectClass(obj);
     jfieldID fid = env->GetFieldID(
     jfieldID fid = env->GetFieldID(
@@ -1019,28 +941,21 @@ JNIEXPORT jobject JNICALL Java_com_zerotierone_sdk_Node_status
         return 0;
         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
     // create a com.zerotierone.sdk.NodeStatus object
+    nodeStatusClass = env->FindClass("com/zerotierone/sdk/NodeStatus");
     if(nodeStatusClass == NULL)
     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)
     if(nodeStatusConstructor == NULL)
     {
     {
-        nodeStatusConstructor = env->GetMethodID(
-            nodeStatusClass, "<init>", "()V");
-        if(nodeStatusConstructor == NULL)
-        {
-            return NULL;
-        }
+        return NULL;
     }
     }
 
 
     jobject nodeStatusObj = env->NewObject(nodeStatusClass, nodeStatusConstructor);
     jobject nodeStatusObj = env->NewObject(nodeStatusClass, nodeStatusConstructor);
@@ -1052,45 +967,33 @@ JNIEXPORT jobject JNICALL Java_com_zerotierone_sdk_Node_status
     ZT1_NodeStatus nodeStatus;
     ZT1_NodeStatus nodeStatus;
     ZT1_Node_status(node, &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)
     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)
     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)
     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)
     if(onlineField == NULL)
     {
     {
-        onlineField = env->GetFieldID(nodeStatusClass, "online", "Z");
-        if(onlineField == NULL)
-        {
-            return NULL;
-        }
+        return NULL;
     }
     }
 
 
     env->SetLongField(nodeStatusObj, addressField, nodeStatus.address);
     env->SetLongField(nodeStatusObj, addressField, nodeStatus.address);