From 4dc0ff8f13a2a5d852cda9302632d58b25d045ac Mon Sep 17 00:00:00 2001 From: Grant Limberg Date: Tue, 9 Jun 2015 23:12:44 -0700 Subject: [PATCH] Replace calls to GetArrayElements with GetPrimitiveArrayCritical. This puts code accessing the data in a critical section so that the GC cannot run while JNI has access to the array. This helps with stability somewhat, but I'm still getting some crashes in the GC --- java/jni/com_zerotierone_sdk_Node.cpp | 54 ++++++++++++++------------- 1 file changed, 29 insertions(+), 25 deletions(-) diff --git a/java/jni/com_zerotierone_sdk_Node.cpp b/java/jni/com_zerotierone_sdk_Node.cpp index 2a90bb85b..62fbba895 100644 --- a/java/jni/com_zerotierone_sdk_Node.cpp +++ b/java/jni/com_zerotierone_sdk_Node.cpp @@ -174,9 +174,9 @@ namespace { return; } - jbyte *data = env->GetByteArrayElements(dataArray, NULL); + void *data = env->GetPrimitiveArrayCritical(dataArray, NULL); memcpy(data, frameData, frameLength); - env->ReleaseByteArrayElements(dataArray, data, 0); + env->ReleasePrimitiveArrayCritical(dataArray, data, 0); if(env->ExceptionCheck()) { @@ -356,13 +356,13 @@ namespace { if(retval > 0) { - jbyte *data = env->GetByteArrayElements(bufferObj, NULL); + void *data = env->GetPrimitiveArrayCritical(bufferObj, NULL); memcpy(buffer, data, retval); - env->ReleaseByteArrayElements(bufferObj, data, JNI_ABORT); + env->ReleasePrimitiveArrayCritical(bufferObj, data, 0); - jlong *objSize = env->GetLongArrayElements(objectSizeObj, NULL); + jlong *objSize = (jlong*)env->GetPrimitiveArrayCritical(objectSizeObj, NULL); *out_objectSize = (unsigned long)objSize[0]; - env->ReleaseLongArrayElements(objectSizeObj, objSize, JNI_ABORT); + env->ReleasePrimitiveArrayCritical(objectSizeObj, objSize, 0); } LOGI("Out Object Size: %lu", *out_objectSize); @@ -700,7 +700,10 @@ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_processVirtualNetworkFrame( unsigned int vlanId = (unsigned int)in_vlanId; unsigned int frameLength = env->GetArrayLength(in_frameData); - jbyte *frameData =env->GetByteArrayElements(in_frameData, NULL); + void *frameData = env->GetPrimitiveArrayCritical(in_frameData, NULL); + void *localData = malloc(frameLength); + memcpy(localData, frameData, frameLength); + env->ReleasePrimitiveArrayCritical(in_frameData, frameData, 0); uint64_t nextBackgroundTaskDeadline = 0; @@ -712,15 +715,15 @@ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_processVirtualNetworkFrame( destMac, etherType, vlanId, - (const void*)frameData, + (const void*)localData, frameLength, &nextBackgroundTaskDeadline); - jlong *outDeadline = env->GetLongArrayElements(out_nextBackgroundTaskDeadline, NULL); - outDeadline[0] = (jlong)nextBackgroundTaskDeadline; - env->ReleaseLongArrayElements(out_nextBackgroundTaskDeadline, outDeadline, 0); + - env->ReleaseByteArrayElements(in_frameData, frameData, 0); + jlong *outDeadline = (jlong*)env->GetPrimitiveArrayCritical(out_nextBackgroundTaskDeadline, NULL); + outDeadline[0] = (jlong)nextBackgroundTaskDeadline; + env->ReleasePrimitiveArrayCritical(out_nextBackgroundTaskDeadline, outDeadline, 0); return createResultObject(env, rc); } @@ -816,8 +819,7 @@ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_processWirePacket( unsigned int addrSize = env->GetArrayLength(addressArray); // get the address bytes - jbyte *addr = env->GetByteArrayElements(addressArray, NULL); - + jbyte *addr = (jbyte*)env->GetPrimitiveArrayCritical(addressArray, NULL); sockaddr_storage remoteAddress = {}; @@ -842,13 +844,16 @@ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_processWirePacket( else { // unknown address type - env->ReleaseByteArrayElements(addressArray, addr, 0); + env->ReleasePrimitiveArrayCritical(addressArray, addr, 0); return createResultObject(env, ZT1_RESULT_FATAL_ERROR_INTERNAL); } - + env->ReleasePrimitiveArrayCritical(addressArray, addr, 0); unsigned int packetLength = env->GetArrayLength(in_packetData); - jbyte *packetData = env->GetByteArrayElements(in_packetData, NULL); + void *packetData = env->GetPrimitiveArrayCritical(in_packetData, NULL); + void *localData = malloc(packetLength); + memcpy(localData, packetData, packetLength); + env->ReleasePrimitiveArrayCritical(in_packetData, packetData, 0); uint64_t nextBackgroundTaskDeadline = 0; @@ -856,7 +861,7 @@ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_processWirePacket( node, now, &remoteAddress, - packetData, + localData, packetLength, &nextBackgroundTaskDeadline); if(rc != ZT1_RESULT_OK) @@ -864,12 +869,11 @@ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_processWirePacket( LOGE("ZT1_Node_processWirePacket returned: %d", rc); } - jlong *outDeadline = env->GetLongArrayElements(out_nextBackgroundTaskDeadline, NULL); - outDeadline[0] = (jlong)nextBackgroundTaskDeadline; - env->ReleaseLongArrayElements(out_nextBackgroundTaskDeadline, outDeadline, 0); + free(localData); - env->ReleaseByteArrayElements(addressArray, addr, 0); - env->ReleaseByteArrayElements(in_packetData, packetData, 0); + jlong *outDeadline = (jlong*)env->GetPrimitiveArrayCritical(out_nextBackgroundTaskDeadline, NULL); + outDeadline[0] = (jlong)nextBackgroundTaskDeadline; + env->ReleasePrimitiveArrayCritical(out_nextBackgroundTaskDeadline, outDeadline, 0); return createResultObject(env, rc); } @@ -904,9 +908,9 @@ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_processBackgroundTasks( ZT1_ResultCode rc = ZT1_Node_processBackgroundTasks(node, now, &nextBackgroundTaskDeadline); - jlong *outDeadline = env->GetLongArrayElements(out_nextBackgroundTaskDeadline, NULL); + jlong *outDeadline = (jlong*)env->GetPrimitiveArrayCritical(out_nextBackgroundTaskDeadline, NULL); outDeadline[0] = (jlong)nextBackgroundTaskDeadline; - env->ReleaseLongArrayElements(out_nextBackgroundTaskDeadline, outDeadline, 0); + env->ReleasePrimitiveArrayCritical(out_nextBackgroundTaskDeadline, outDeadline, 0); return createResultObject(env, rc); }