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:
fur 1998-06-28 07:53:04 +00:00
parent 4f4552540c
commit 3b5246d547
5 changed files with 81 additions and 19 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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);