Skip to content

Commit d45e0a9

Browse files
committed
added check for reference counting
1 parent 8fe9427 commit d45e0a9

8 files changed

Lines changed: 46 additions & 3 deletions

File tree

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,9 @@ __Example__
194194

195195
Creates a new java Proxy for the given interface. Functions passed in will run on the v8 main thread and not a new thread.
196196

197+
The returned object has two methods ref() and unref() which you can use to maintain references to prevent premature
198+
garbage collection. You must call these methods to ensure the proxy stays around.
199+
197200
__Arguments__
198201

199202
* interfaceName - The name of the interface to proxy. For subclasses seperate using a '$' (eg. com.nearinfinty.MyClass$SubClass)
92 Bytes
Binary file not shown.

src-java/node/NodeDynamicProxyClass.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,12 @@ public Object invoke(Object proxy, java.lang.reflect.Method m, Object[] args) th
1818
{
1919
return callJs(this.ptr, m, args);
2020
}
21+
22+
public void ref() {
23+
24+
}
25+
26+
public void unref() {
27+
28+
}
2129
}

src/java.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,8 @@ v8::Handle<v8::Value> Java::createJVM(JavaVM** jvm, JNIEnv** env) {
245245
ARGS_FRONT_OBJECT(functions);
246246

247247
DynamicProxyData* dynamicProxyData = new DynamicProxyData();
248+
dynamicProxyData->markerStart = DYNAMIC_PROXY_DATA_MARKER_START;
249+
dynamicProxyData->markerEnd = DYNAMIC_PROXY_DATA_MARKER_END;
248250
dynamicProxyData->java = self;
249251
dynamicProxyData->interfaceName = interfaceName;
250252
dynamicProxyData->functions = v8::Persistent<v8::Object>::New(functions);
@@ -598,6 +600,9 @@ void EIO_CallJs(uv_work_t* req) {
598600

599601
void EIO_AfterCallJs(uv_work_t* req) {
600602
DynamicProxyData* dynamicProxyData = static_cast<DynamicProxyData*>(req->data);
603+
if(!dynamicProxyDataVerify(dynamicProxyData)) {
604+
return;
605+
}
601606
dynamicProxyData->result = NULL;
602607

603608
JNIEnv* env = dynamicProxyData->env;
@@ -631,6 +636,9 @@ void EIO_AfterCallJs(uv_work_t* req) {
631636
}
632637
v8Result = fn->Call(dynamicProxyData->functions, argc, argv);
633638
delete[] argv;
639+
if(!dynamicProxyDataVerify(dynamicProxyData)) {
640+
return;
641+
}
634642

635643
javaResult = v8ToJava(env, v8Result);
636644
if(javaResult == NULL) {
@@ -668,6 +676,9 @@ JNIEXPORT jobject JNICALL Java_node_NodeDynamicProxyClass_callJs(JNIEnv *env, jo
668676
}
669677
}
670678

679+
if(!dynamicProxyDataVerify(dynamicProxyData)) {
680+
return NULL;
681+
}
671682
if(dynamicProxyData->result) {
672683
env->DeleteGlobalRef(dynamicProxyData->result);
673684
}

src/javaObject.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,9 @@ JavaObject::~JavaObject() {
6767
if(env->IsInstanceOf(m_obj, nodeDynamicProxyClass)) {
6868
jfieldID ptrField = env->GetFieldID(nodeDynamicProxyClass, "ptr", "J");
6969
DynamicProxyData* proxyData = (DynamicProxyData*)(long)env->GetLongField(m_obj, ptrField);
70-
delete proxyData;
70+
if(dynamicProxyDataVerify(proxyData)) {
71+
delete proxyData;
72+
}
7173
}
7274

7375
m_java->getJavaEnv()->DeleteGlobalRef(m_obj);

src/node_NodeDynamicProxyClass.h

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/utils.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,9 @@ jobject v8ToJava(JNIEnv* env, v8::Local<v8::Value> arg) {
208208
if(env->IsInstanceOf(jobj, nodeDynamicProxyClass)) {
209209
jfieldID ptrField = env->GetFieldID(nodeDynamicProxyClass, "ptr", "J");
210210
DynamicProxyData* proxyData = (DynamicProxyData*)(long)env->GetLongField(jobj, ptrField);
211+
if(!dynamicProxyDataVerify(proxyData)) {
212+
return NULL;
213+
}
211214

212215
jclass dynamicInterface = javaFindClass(env, proxyData->interfaceName);
213216
if(dynamicInterface == NULL) {
@@ -431,4 +434,13 @@ jobject longToJavaLongObj(JNIEnv *env, long val) {
431434
jclass longClass = env->FindClass("java/lang/Long");
432435
jmethodID constructor = env->GetMethodID(longClass, "<init>", "(J)V");
433436
return env->NewObject(longClass, constructor, val);
434-
}
437+
}
438+
439+
int dynamicProxyDataVerify(DynamicProxyData* data) {
440+
if(data->markerStart == DYNAMIC_PROXY_DATA_MARKER_START && data->markerEnd == DYNAMIC_PROXY_DATA_MARKER_END) {
441+
return 1;
442+
}
443+
444+
printf("*** ERROR: Lost reference to the dynamic proxy. You must maintain a reference in javascript land using ref() and unref(). ***\n");
445+
return 0;
446+
}

src/utils.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ typedef enum _jvalueType {
2525
} jvalueType;
2626

2727
struct DynamicProxyData {
28+
unsigned int markerStart;
2829
JNIEnv* env;
2930
Java* java;
3031
std::string interfaceName;
@@ -33,8 +34,14 @@ struct DynamicProxyData {
3334
jobjectArray args;
3435
jobject result;
3536
int done;
37+
unsigned int markerEnd;
3638
};
3739

40+
#define DYNAMIC_PROXY_DATA_MARKER_START 0x12345678
41+
#define DYNAMIC_PROXY_DATA_MARKER_END 0x87654321
42+
43+
int dynamicProxyDataVerify(DynamicProxyData* data);
44+
3845
std::list<jobject> javaReflectionGetMethods(JNIEnv *env, jclass clazz);
3946
std::list<jobject> javaReflectionGetFields(JNIEnv *env, jclass clazz);
4047
std::string javaToString(JNIEnv *env, jstring str);

0 commit comments

Comments
 (0)