mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 11:25:00 +00:00
Aggressively track and release JNI local references to constructed
Java objects, because otherwise at least one JVM is reticent about GC'ing them.
This commit is contained in:
parent
4f4552540c
commit
3b5246d547
@ -146,6 +146,12 @@ jsj_WrapJSObject(JSContext *cx, JNIEnv *jEnv, JSObject *js_obj)
|
||||
java_wrapper_obj = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Release local reference to wrapper object, since some JVMs seem reticent
|
||||
* about collecting it otherwise.
|
||||
*/
|
||||
(*jEnv)->DeleteLocalRef(jEnv, java_wrapper_obj);
|
||||
|
||||
done:
|
||||
#ifdef JS_THREADSAFE
|
||||
PR_ExitMonitor(js_obj_reflections_monitor);
|
||||
@ -389,6 +395,15 @@ throw_any_pending_js_error_as_a_java_exception(JSJavaThreadState *jsj_env)
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
* Release local references to Java objects, since some JVMs seem reticent
|
||||
* about collecting them otherwise.
|
||||
*/
|
||||
(*jEnv)->DeleteLocalRef(jEnv, message_jstr);
|
||||
(*jEnv)->DeleteLocalRef(jEnv, filename_jstr);
|
||||
(*jEnv)->DeleteLocalRef(jEnv, linebuf_jstr);
|
||||
(*jEnv)->DeleteLocalRef(jEnv, java_exception);
|
||||
|
||||
goto done;
|
||||
|
||||
out_of_memory:
|
||||
@ -639,6 +654,7 @@ Java_netscape_javascript_JSObject_getMember(JNIEnv *jEnv,
|
||||
JSObject *js_obj;
|
||||
jsval js_val;
|
||||
int dummy_cost;
|
||||
JSBool dummy_bool;
|
||||
const jchar *property_name_ucs2;
|
||||
jsize property_name_len;
|
||||
JSErrorReporter saved_reporter;
|
||||
@ -669,7 +685,7 @@ Java_netscape_javascript_JSObject_getMember(JNIEnv *jEnv,
|
||||
goto done;
|
||||
|
||||
jsj_ConvertJSValueToJavaObject(cx, jEnv, js_val, get_jlObject_descriptor(cx, jEnv),
|
||||
&dummy_cost, &member);
|
||||
&dummy_cost, &member, &dummy_bool);
|
||||
|
||||
done:
|
||||
if (property_name_ucs2)
|
||||
@ -694,6 +710,7 @@ Java_netscape_javascript_JSObject_getSlot(JNIEnv *jEnv,
|
||||
JSObject *js_obj;
|
||||
jsval js_val;
|
||||
int dummy_cost;
|
||||
JSBool dummy_bool;
|
||||
JSErrorReporter saved_reporter;
|
||||
jobject member;
|
||||
JSJavaThreadState *jsj_env;
|
||||
@ -706,7 +723,7 @@ Java_netscape_javascript_JSObject_getSlot(JNIEnv *jEnv,
|
||||
if (!JS_GetElement(cx, js_obj, slot, &js_val))
|
||||
goto done;
|
||||
if (!jsj_ConvertJSValueToJavaObject(cx, jEnv, js_val, get_jlObject_descriptor(cx, jEnv),
|
||||
&dummy_cost, &member))
|
||||
&dummy_cost, &member, &dummy_bool))
|
||||
goto done;
|
||||
|
||||
done:
|
||||
@ -854,6 +871,7 @@ Java_netscape_javascript_JSObject_call(JNIEnv *jEnv, jobject java_wrapper_obj,
|
||||
JSObject *js_obj;
|
||||
jsval js_val, function_val;
|
||||
int dummy_cost;
|
||||
JSBool dummy_bool;
|
||||
const jchar *function_name_ucs2;
|
||||
jsize function_name_len;
|
||||
JSErrorReporter saved_reporter;
|
||||
@ -908,7 +926,7 @@ Java_netscape_javascript_JSObject_call(JNIEnv *jEnv, jobject java_wrapper_obj,
|
||||
goto cleanup_argv;
|
||||
|
||||
jsj_ConvertJSValueToJavaObject(cx, jEnv, js_val, get_jlObject_descriptor(cx, jEnv),
|
||||
&dummy_cost, &result);
|
||||
&dummy_cost, &result, &dummy_bool);
|
||||
|
||||
cleanup_argv:
|
||||
if (argv) {
|
||||
@ -943,6 +961,7 @@ Java_netscape_javascript_JSObject_eval(JNIEnv *jEnv,
|
||||
JSObject *js_obj;
|
||||
jsval js_val;
|
||||
int dummy_cost;
|
||||
JSBool dummy_bool;
|
||||
const jchar *eval_ucs2;
|
||||
jsize eval_len;
|
||||
JSErrorReporter saved_reporter;
|
||||
@ -984,7 +1003,7 @@ Java_netscape_javascript_JSObject_eval(JNIEnv *jEnv,
|
||||
|
||||
/* Convert result to a subclass of java.lang.Object */
|
||||
jsj_ConvertJSValueToJavaObject(cx, jEnv, js_val, get_jlObject_descriptor(cx, jEnv),
|
||||
&dummy_cost, &result);
|
||||
&dummy_cost, &result, &dummy_bool);
|
||||
|
||||
done:
|
||||
if (eval_ucs2)
|
||||
@ -1043,6 +1062,7 @@ Java_netscape_javascript_JSObject_getWindow(JNIEnv *jEnv,
|
||||
JSObject *js_obj;
|
||||
jsval js_val;
|
||||
int dummy_cost;
|
||||
JSBool dummy_bool;
|
||||
JSErrorReporter saved_reporter;
|
||||
jobject java_obj;
|
||||
JSJavaThreadState *jsj_env;
|
||||
@ -1063,7 +1083,7 @@ Java_netscape_javascript_JSObject_getWindow(JNIEnv *jEnv,
|
||||
}
|
||||
js_val = OBJECT_TO_JSVAL(js_obj);
|
||||
jsj_ConvertJSValueToJavaObject(cx, jEnv, js_val, get_jlObject_descriptor(cx, jEnv),
|
||||
&dummy_cost, &java_obj);
|
||||
&dummy_cost, &java_obj, &dummy_bool);
|
||||
done:
|
||||
if (!exit_js(cx, jsj_env, saved_reporter))
|
||||
return NULL;
|
||||
|
@ -112,9 +112,10 @@ jsj_SetJavaArrayElement(JSContext *cx, JNIEnv *jEnv, jarray java_array, jsize in
|
||||
int dummy_cost;
|
||||
jvalue java_value;
|
||||
JavaSignatureChar component_type;
|
||||
JSBool is_local_ref;
|
||||
|
||||
if (!jsj_ConvertJSValueToJavaValue(cx, jEnv, js_val, array_component_signature,
|
||||
&dummy_cost, &java_value))
|
||||
&dummy_cost, &java_value, &is_local_ref))
|
||||
return JS_FALSE;
|
||||
|
||||
#define SET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Type,member) \
|
||||
@ -163,6 +164,8 @@ jsj_SetJavaArrayElement(JSContext *cx, JNIEnv *jEnv, jarray java_array, jsize in
|
||||
case JAVA_SIGNATURE_CLASS:
|
||||
case JAVA_SIGNATURE_ARRAY:
|
||||
(*jEnv)->SetObjectArrayElement(jEnv, java_array, index, java_value.l);
|
||||
if (is_local_ref) \
|
||||
(*jEnv)->DeleteLocalRef(jEnv, java_value.l);
|
||||
if ((*jEnv)->ExceptionOccurred(jEnv)) {
|
||||
jsj_ReportJavaError(cx, jEnv, "Error assigning to Java object array");
|
||||
return JS_FALSE;
|
||||
|
@ -307,7 +307,7 @@ JSBool
|
||||
jsj_SetJavaFieldValue(JSContext *cx, JNIEnv *jEnv, JavaFieldSpec *field_spec,
|
||||
jclass java_obj, jsval js_val)
|
||||
{
|
||||
JSBool is_static_field;
|
||||
JSBool is_static_field, is_local_ref;
|
||||
int dummy_cost;
|
||||
jvalue java_value;
|
||||
JavaSignature *signature;
|
||||
@ -331,7 +331,8 @@ jsj_SetJavaFieldValue(JSContext *cx, JNIEnv *jEnv, JavaFieldSpec *field_spec,
|
||||
PR_END_MACRO
|
||||
|
||||
signature = field_spec->signature;
|
||||
if (!jsj_ConvertJSValueToJavaValue(cx, jEnv, js_val, signature, &dummy_cost, &java_value))
|
||||
if (!jsj_ConvertJSValueToJavaValue(cx, jEnv, js_val, signature, &dummy_cost,
|
||||
&java_value, &is_local_ref))
|
||||
return JS_FALSE;
|
||||
|
||||
field_type = signature->type;
|
||||
@ -371,6 +372,8 @@ jsj_SetJavaFieldValue(JSContext *cx, JNIEnv *jEnv, JavaFieldSpec *field_spec,
|
||||
case JAVA_SIGNATURE_CLASS:
|
||||
case JAVA_SIGNATURE_ARRAY:
|
||||
SET_JAVA_FIELD(Object,l);
|
||||
if (is_local_ref) \
|
||||
(*jEnv)->DeleteLocalRef(jEnv, java_value.l);
|
||||
break;
|
||||
|
||||
#undef SET_JAVA_FIELD
|
||||
|
@ -548,13 +548,15 @@ method_signature_matches_JS_args(JSContext *cx, JNIEnv *jEnv, uintN argc, jsval
|
||||
{
|
||||
uintN i;
|
||||
JavaSignature *arg_signature;
|
||||
JSBool dummy_bool;
|
||||
|
||||
if (argc != (uintN)method_signature->num_args)
|
||||
return JS_FALSE;
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
arg_signature = method_signature->arg_signatures[i];
|
||||
if (!jsj_ConvertJSValueToJavaValue(cx, jEnv, argv[i], arg_signature, cost, NULL))
|
||||
if (!jsj_ConvertJSValueToJavaValue(cx, jEnv, argv[i], arg_signature, cost,
|
||||
NULL, &dummy_bool))
|
||||
return JS_FALSE;
|
||||
}
|
||||
return JS_TRUE;
|
||||
@ -678,7 +680,7 @@ resolve_overloaded_method(JSContext *cx, JNIEnv *jEnv, JavaMemberDescriptor *mem
|
||||
if (!method_signature_matches_JS_args(cx, jEnv, argc, argv, &method->signature, &cost))
|
||||
continue;
|
||||
|
||||
#ifdef LIVECONNECT_IMPROVEMENTS
|
||||
#if 1
|
||||
if (cost < lowest_cost) {
|
||||
lowest_cost = cost;
|
||||
best_method_match = method;
|
||||
@ -708,10 +710,10 @@ resolve_overloaded_method(JSContext *cx, JNIEnv *jEnv, JavaMemberDescriptor *mem
|
||||
|
||||
static jvalue *
|
||||
convert_JS_method_args_to_java_argv(JSContext *cx, JNIEnv *jEnv, jsval *argv,
|
||||
JavaMethodSpec *method)
|
||||
JavaMethodSpec *method, JSBool **localvp)
|
||||
{
|
||||
jvalue *jargv;
|
||||
JSBool ok;
|
||||
JSBool ok, *localv;
|
||||
uintN i, argc;
|
||||
JavaSignature **arg_signatures;
|
||||
JavaMethodSignature *signature;
|
||||
@ -727,14 +729,27 @@ convert_JS_method_args_to_java_argv(JSContext *cx, JNIEnv *jEnv, jsval *argv,
|
||||
if (!jargv)
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* Allocate an array that contains a flag for each argument, indicating whether
|
||||
* or not the conversion from a JS value to a Java value resulted in a new
|
||||
* JNI local reference.
|
||||
*/
|
||||
localv = (JSBool *)JS_malloc(cx, sizeof(JSBool) * argc);
|
||||
if (!localv) {
|
||||
JS_free(cx, jargv);
|
||||
return NULL;
|
||||
}
|
||||
*localvp = localv;
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
int dummy_cost;
|
||||
|
||||
ok = jsj_ConvertJSValueToJavaValue(cx, jEnv, argv[i], arg_signatures[i],
|
||||
&dummy_cost, &jargv[i]);
|
||||
&dummy_cost, &jargv[i], &localv[i]);
|
||||
if (!ok) {
|
||||
JS_ReportError(cx, "Internal error: can't convert JS value to Java value");
|
||||
JS_free(cx, jargv);
|
||||
JS_free(cx, localv);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@ -752,7 +767,7 @@ invoke_java_method(JSContext *cx, JSJavaThreadState *jsj_env,
|
||||
{
|
||||
jvalue java_value;
|
||||
jvalue *jargv;
|
||||
uintN argc;
|
||||
uintN argc, i;
|
||||
jobject java_object;
|
||||
jclass java_class;
|
||||
jmethodID methodID;
|
||||
@ -760,6 +775,7 @@ invoke_java_method(JSContext *cx, JSJavaThreadState *jsj_env,
|
||||
JavaSignature *return_val_signature;
|
||||
JSContext *old_cx;
|
||||
JNIEnv *jEnv;
|
||||
JSBool *localv;
|
||||
|
||||
methodID = method->methodID;
|
||||
signature = &method->signature;
|
||||
@ -777,7 +793,7 @@ invoke_java_method(JSContext *cx, JSJavaThreadState *jsj_env,
|
||||
|
||||
jargv = NULL;
|
||||
if (argc) {
|
||||
jargv = convert_JS_method_args_to_java_argv(cx, jEnv, argv, method);
|
||||
jargv = convert_JS_method_args_to_java_argv(cx, jEnv, argv, method, &localv);
|
||||
if (!jargv)
|
||||
return JS_FALSE;
|
||||
}
|
||||
@ -858,12 +874,22 @@ invoke_java_method(JSContext *cx, JSJavaThreadState *jsj_env,
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (localv[i])
|
||||
(*jEnv)->DeleteLocalRef(jEnv, jargv[i].l);
|
||||
}
|
||||
if (jargv)
|
||||
JS_free(cx, jargv);
|
||||
|
||||
JSJ_SetDefaultJSContextForJavaThread(old_cx, jsj_env);
|
||||
|
||||
return jsj_ConvertJavaValueToJSValue(cx, jEnv, return_val_signature, &java_value, vp);
|
||||
|
||||
error:
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (localv[i])
|
||||
(*jEnv)->DeleteLocalRef(jEnv, jargv[i].l);
|
||||
}
|
||||
if (jargv)
|
||||
JS_free(cx, jargv);
|
||||
JSJ_SetDefaultJSContextForJavaThread(old_cx, jsj_env);
|
||||
@ -987,12 +1013,13 @@ invoke_java_constructor(JSContext *cx,
|
||||
jsval *argv, jsval *vp)
|
||||
{
|
||||
jvalue *jargv;
|
||||
uintN argc;
|
||||
uintN argc, i;
|
||||
jobject java_object;
|
||||
jmethodID methodID;
|
||||
JavaMethodSignature *signature;
|
||||
JSContext *old_cx;
|
||||
JNIEnv *jEnv;
|
||||
JSBool *localv;
|
||||
|
||||
methodID = method->methodID;
|
||||
signature = &method->signature;
|
||||
@ -1002,7 +1029,7 @@ invoke_java_constructor(JSContext *cx,
|
||||
|
||||
jargv = NULL;
|
||||
if (argc) {
|
||||
jargv = convert_JS_method_args_to_java_argv(cx, jEnv, argv, method);
|
||||
jargv = convert_JS_method_args_to_java_argv(cx, jEnv, argv, method, &localv);
|
||||
if (!jargv)
|
||||
return JS_FALSE;
|
||||
}
|
||||
@ -1013,6 +1040,7 @@ invoke_java_constructor(JSContext *cx,
|
||||
"one JSContext ?");
|
||||
}
|
||||
|
||||
/* Call the constructor */
|
||||
java_object = (*jEnv)->NewObjectA(jEnv, java_class, methodID, jargv);
|
||||
|
||||
JSJ_SetDefaultJSContextForJavaThread(old_cx, jsj_env);
|
||||
@ -1023,12 +1051,20 @@ invoke_java_constructor(JSContext *cx,
|
||||
goto error;
|
||||
}
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (localv[i])
|
||||
(*jEnv)->DeleteLocalRef(jEnv, jargv[i].l);
|
||||
}
|
||||
if (jargv)
|
||||
JS_free(cx, jargv);
|
||||
|
||||
return jsj_ConvertJavaObjectToJSValue(cx, jEnv, java_object, vp);
|
||||
|
||||
error:
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (localv[i])
|
||||
(*jEnv)->DeleteLocalRef(jEnv, jargv[i].l);
|
||||
}
|
||||
if (jargv)
|
||||
JS_free(cx, jargv);
|
||||
return JS_FALSE;
|
||||
|
@ -268,10 +268,10 @@ jsj_PurgeJavaMethodSignature(JSContext *cx, JNIEnv *jEnv, JavaMethodSignature *s
|
||||
|
||||
extern JSBool
|
||||
jsj_ConvertJSValueToJavaValue(JSContext *cx, JNIEnv *jEnv, jsval v, JavaSignature *signature,
|
||||
int *cost, jvalue *java_value);
|
||||
int *cost, jvalue *java_value, JSBool *is_local_refp);
|
||||
extern JSBool
|
||||
jsj_ConvertJSValueToJavaObject(JSContext *cx, JNIEnv *jEnv, jsval v, JavaSignature *signature,
|
||||
int *cost, jobject *java_value);
|
||||
int *cost, jobject *java_value, JSBool *is_local_refp);
|
||||
extern jstring
|
||||
jsj_ConvertJSStringToJavaString(JSContext *cx, JNIEnv *jEnv, JSString *js_str);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user