Commit 9996b441 authored by Jacob Potter's avatar Jacob Potter

Avoid calling JNI during critical section. Fixes #76

parent 249b6174
......@@ -152,11 +152,38 @@ namespace djinni
static CppType toCpp(JNIEnv* jniEnv, JniType j)
{
assert(j != nullptr);
auto deleter = [jniEnv, j] (void* c) { jniEnv->ReleasePrimitiveArrayCritical(j, c, JNI_ABORT); };
std::unique_ptr<uint8_t, decltype(deleter)> ptr(reinterpret_cast<uint8_t*>(jniEnv->GetPrimitiveArrayCritical(j, nullptr)),
deleter);
std::vector<uint8_t> ret;
jsize length = jniEnv->GetArrayLength(j);
jniExceptionCheck(jniEnv);
return {ptr.get(), ptr.get() + jniEnv->GetArrayLength(j)};
if (!length) {
return {};
}
{
auto deleter = [jniEnv, j] (void* c) {
if (c) {
jniEnv->ReleasePrimitiveArrayCritical(j, c, JNI_ABORT);
}
};
std::unique_ptr<uint8_t, decltype(deleter)> ptr(
reinterpret_cast<uint8_t*>(jniEnv->GetPrimitiveArrayCritical(j, nullptr)),
deleter
);
if (ptr) {
// Construct and then move-assign. This copies the elements only once,
// and avoids having to initialize before filling (as with resize())
ret = std::vector<uint8_t>{ptr.get(), ptr.get() + length};
} else {
// Something failed...
jniExceptionCheck(jniEnv);
}
}
return ret;
}
static LocalRef<JniType> fromCpp(JNIEnv* jniEnv, const CppType& c)
......
......@@ -30,4 +30,6 @@ test_helpers = interface +c {
# Ensures that we generate integer translation code
static assorted_integers_id(i: assorted_integers): assorted_integers;
static id_binary(b: binary): binary;
}
......@@ -14,6 +14,7 @@
#include <memory>
#include <string>
#include <unordered_map>
#include <vector>
class ClientInterface;
class Token;
......@@ -66,4 +67,6 @@ public:
/** Ensures that we generate integer translation code */
static AssortedIntegers assorted_integers_id(const AssortedIntegers & i);
static std::vector<uint8_t> id_binary(const std::vector<uint8_t> & b);
};
......@@ -52,6 +52,8 @@ public abstract class TestHelpers {
/** Ensures that we generate integer translation code */
public static native AssortedIntegers assortedIntegersId(AssortedIntegers i);
public static native byte[] idBinary(byte[] b);
public static final class CppProxy extends TestHelpers
{
private final long nativeRef;
......
......@@ -220,4 +220,13 @@ CJNIEXPORT jobject JNICALL Java_com_dropbox_djinni_test_TestHelpers_assortedInte
} JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, 0 /* value doesn't matter */)
}
CJNIEXPORT jbyteArray JNICALL Java_com_dropbox_djinni_test_TestHelpers_idBinary(JNIEnv* jniEnv, jobject /*this*/, jbyteArray j_b)
{
try {
DJINNI_FUNCTION_PROLOGUE0(jniEnv);
auto r = ::TestHelpers::id_binary(::djinni::Binary::toCpp(jniEnv, j_b));
return ::djinni::Binary::fromCpp(jniEnv, r).release();
} JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, 0 /* value doesn't matter */)
}
} // namespace djinni_generated
......@@ -202,4 +202,11 @@ auto TestHelpers::fromCpp(const CppType& cpp) -> ObjcType
} DJINNI_TRANSLATE_EXCEPTIONS()
}
+ (nonnull NSData *)idBinary:(nonnull NSData *)b {
try {
auto r = ::TestHelpers::id_binary(::djinni::Binary::toCpp(b));
return ::djinni::Binary::fromCpp(r);
} DJINNI_TRANSLATE_EXCEPTIONS()
}
@end
......@@ -59,4 +59,6 @@
/** Ensures that we generate integer translation code */
+ (nonnull DBAssortedIntegers *)assortedIntegersId:(nonnull DBAssortedIntegers *)i;
+ (nonnull NSData *)idBinary:(nonnull NSData *)b;
@end
......@@ -130,3 +130,7 @@ void TestHelpers::check_enum(color) {} // stub
AssortedIntegers TestHelpers::assorted_integers_id(const AssortedIntegers & i) {
return i;
}
std::vector<uint8_t> TestHelpers::id_binary(const std::vector<uint8_t> & v) {
return v;
}
......@@ -3,6 +3,7 @@ package com.dropbox.djinni.test;
import junit.framework.TestCase;
import java.util.ArrayList;
import java.util.Arrays;
public class PrimitiveListTest extends TestCase {
......@@ -27,4 +28,10 @@ public class PrimitiveListTest extends TestCase {
PrimitiveList converted = TestHelpers.getPrimitiveList();
assertEquals(converted.getList(), jPrimitiveList.getList());
}
public void testBinary()
{
byte[] b = { 1, 2, 3 };
assertTrue(Arrays.equals(TestHelpers.idBinary(b), b));
}
}
......@@ -11,8 +11,9 @@
<src path="../generated-src"/>
<src path="../handwritten-src"/>
</javac>
<java classname="org.junit.runner.JUnitCore">
<java classname="org.junit.runner.JUnitCore" fork="true">
<classpath path="hamcrest-core-1.3.jar:junit-4.11.jar:classes"/>
<jvmarg value="-Xcheck:jni"/>
<arg value="com.dropbox.djinni.test.AllTests"/>
</java>
</target>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment