⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jsj_javaobject.c

📁 caffeine-monkey java实现的js模拟引擎
💻 C
📖 第 1 页 / 共 3 页
字号:
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Mozilla Communicator client code, released * March 31, 1998. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1998 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * This Original Code has been modified by IBM Corporation. Modifications made * by IBM described herein are Copyright (c) International Business Machines * Corporation, 2000. * Modifications to Mozilla code or documentation identified per MPL Section 3.3 * * Date             Modified by     Description of modification * 04/20/2000       IBM Corp.      OS/2 VisualAge build. * * ***** END LICENSE BLOCK ***** *//* * This file is part of the Java-vendor-neutral implementation of LiveConnect * * It contains the native code implementation of JS's JavaObject class. * * An instance of JavaObject is the JavaScript reflection of a Java object. * */#include <stdlib.h>#include <string.h>#include "jsobj.h"#include "jsj_private.h"      /* LiveConnect internals */#include "jsj_hash.h"         /* Hash table with Java object as key */#ifdef JSJ_THREADSAFE#include "prmon.h"#endif/* * This is a hash table that maps from Java objects to JS objects. * It is used to ensure that the same JS object is obtained when a Java * object is reflected more than once, so that JS object equality tests * work in the expected manner, i.e. the "==" and "===" operators. * * The table entry keys are Java objects (of type jobject) and the entry values * are JSObject pointers.  Because the jobject type is an opaque handle and * not necessarily a pointer, the hashing and key comparison functions must * invoke the appropriate JVM functions. * * When the corresponding JS object instance is finalized, the entry is * removed from the table, and a Java GC root for the Java object is removed. */static JSJHashTable *java_obj_reflections = NULL;#ifdef JSJ_THREADSAFEstatic PRMonitor *java_obj_reflections_monitor = NULL;static int java_obj_reflections_mutation_count = 0;#endifstatic JSBool installed_GC_callback = JS_FALSE;static JSGCCallback old_GC_callback = NULL;static JavaObjectWrapper* deferred_wrappers = NULL;static JSBool JS_DLL_CALLBACK jsj_GC_callback(JSContext *cx, JSGCStatus status){    if (status == JSGC_END && deferred_wrappers) {        JNIEnv *jEnv;        JSJavaThreadState *jsj_env = jsj_EnterJava(cx, &jEnv);        if (jEnv) {            JavaObjectWrapper* java_wrapper = deferred_wrappers;            while (java_wrapper) {                deferred_wrappers = java_wrapper->u.next;                if (java_wrapper->java_obj)                    (*jEnv)->DeleteGlobalRef(jEnv, java_wrapper->java_obj);                jsj_ReleaseJavaClassDescriptor(cx, jEnv, java_wrapper->class_descriptor);                JS_free(cx, java_wrapper);                java_wrapper = deferred_wrappers;            }            jsj_ExitJava(jsj_env);        }    }    /* always chain to old GC callback if non-null. */    return old_GC_callback ? old_GC_callback(cx, status) : JS_TRUE;}JSBooljsj_InitJavaObjReflectionsTable(void){    JS_ASSERT(!java_obj_reflections);    java_obj_reflections =        JSJ_NewHashTable(512, jsj_HashJavaObject, jsj_JavaObjectComparator,                         NULL, NULL, NULL);    if (!java_obj_reflections)        return JS_FALSE;#ifdef JSJ_THREADSAFE    java_obj_reflections_monitor = (struct PRMonitor *) PR_NewMonitor();    if (!java_obj_reflections_monitor) {        JSJ_HashTableDestroy(java_obj_reflections);        return JS_FALSE;    }#endif    return JS_TRUE;}JSObject *jsj_WrapJavaObject(JSContext *cx,                   JNIEnv *jEnv,                   jobject java_obj,                   jclass java_class){    JSJHashNumber hash_code;    JSClass *js_class;    JSObject *js_wrapper_obj;    JavaObjectWrapper *java_wrapper;    JavaClassDescriptor *class_descriptor;    JSJHashEntry *he, **hep;#ifdef JSJ_THREADSAFE    int mutation_count;#endif    js_wrapper_obj = NULL;    hash_code = jsj_HashJavaObject((void*)java_obj, (void*)jEnv);#ifdef JSJ_THREADSAFE    PR_EnterMonitor(java_obj_reflections_monitor);#endif    if (!installed_GC_callback) {        /*         * Hook into GC callback mechanism, so we can defer deleting global         * references until it's safe.         */        old_GC_callback =  JS_SetGCCallback(cx, jsj_GC_callback);        installed_GC_callback = JS_TRUE;    }    hep = JSJ_HashTableRawLookup(java_obj_reflections,                                 hash_code, java_obj, (void*)jEnv);    he = *hep;#ifdef JSJ_THREADSAFE    /* Track mutations to hash table */    mutation_count = java_obj_reflections_mutation_count;    /* We must temporarily release this monitor so as to avoid       deadlocks with the JS GC.  See Bugsplat #354852 */    PR_ExitMonitor(java_obj_reflections_monitor);#endif    if (he) {        js_wrapper_obj = (JSObject *)he->value;        if (js_wrapper_obj)            return js_wrapper_obj;    }    /* No existing reflection found.  Construct a new one */    class_descriptor = jsj_GetJavaClassDescriptor(cx, jEnv, java_class);    if (!class_descriptor)        return NULL;    if (class_descriptor->type == JAVA_SIGNATURE_ARRAY) {        js_class = &JavaArray_class;    } else {        JS_ASSERT(IS_OBJECT_TYPE(class_descriptor->type));        js_class = &JavaObject_class;    }    /* Create new JS object to reflect Java object */    js_wrapper_obj = JS_NewObject(cx, js_class, NULL, NULL);    if (!js_wrapper_obj)        return NULL;    /* Create private, native portion of JavaObject */    java_wrapper =        (JavaObjectWrapper *)JS_malloc(cx, sizeof(JavaObjectWrapper));    if (!java_wrapper) {        jsj_ReleaseJavaClassDescriptor(cx, jEnv, class_descriptor);        return NULL;    }    JS_SetPrivate(cx, js_wrapper_obj, java_wrapper);    java_wrapper->class_descriptor = class_descriptor;    java_wrapper->java_obj = NULL;#ifdef JSJ_THREADSAFE    PR_EnterMonitor(java_obj_reflections_monitor);    /* We may need to do the hash table lookup again, since some other       thread may have updated it while the lock wasn't being held. */    if (mutation_count != java_obj_reflections_mutation_count) {        hep = JSJ_HashTableRawLookup(java_obj_reflections,                                     hash_code, java_obj, (void*)jEnv);        he = *hep;        if (he) {            js_wrapper_obj = (JSObject *)he->value;            if (js_wrapper_obj) {                PR_ExitMonitor(java_obj_reflections_monitor);                return js_wrapper_obj;            }        }    }    java_obj_reflections_mutation_count++;#endif    java_obj = (*jEnv)->NewGlobalRef(jEnv, java_obj);    java_wrapper->java_obj = java_obj;    if (!java_obj)        goto out_of_memory;    /* cache the hash code for all time. */    java_wrapper->u.hash_code = hash_code;    /* Add the JavaObject to the hash table */    he = JSJ_HashTableRawAdd(java_obj_reflections, hep, hash_code,                             java_obj, js_wrapper_obj, (void*)jEnv);#ifdef JSJ_THREADSAFE    PR_ExitMonitor(java_obj_reflections_monitor);#endif    if (!he) {        (*jEnv)->DeleteGlobalRef(jEnv, java_obj);        goto out_of_memory;    }    return js_wrapper_obj;out_of_memory:    /* No need to free js_wrapper_obj, as it will be finalized by GC. */    JS_ReportOutOfMemory(cx);    return NULL;}static voidremove_java_obj_reflection_from_hashtable(jobject java_obj, JSJHashNumber hash_code){    JSJHashEntry *he, **hep;#ifdef JSJ_THREADSAFE    PR_EnterMonitor(java_obj_reflections_monitor);#endif    hep = JSJ_HashTableRawLookup(java_obj_reflections, hash_code,                                 java_obj, NULL);    he = *hep;    JS_ASSERT(he);    if (he)        JSJ_HashTableRawRemove(java_obj_reflections, hep, he, NULL);#ifdef JSJ_THREADSAFE    java_obj_reflections_mutation_count++;    PR_ExitMonitor(java_obj_reflections_monitor);#endif}JS_EXPORT_API(void)JavaObject_finalize(JSContext *cx, JSObject *obj){    JavaObjectWrapper *java_wrapper;    jobject java_obj;    JNIEnv *jEnv;    JSJavaThreadState *jsj_env;    java_wrapper = JS_GetPrivate(cx, obj);    if (!java_wrapper)        return;    java_obj = java_wrapper->java_obj;    if (java_obj) {        remove_java_obj_reflection_from_hashtable(java_obj, java_wrapper->u.hash_code);        /* defer releasing global refs until it is safe to do so. */        java_wrapper->u.next = deferred_wrappers;        deferred_wrappers = java_wrapper;    } else {        jsj_env = jsj_EnterJava(cx, &jEnv);        if (jEnv) {            jsj_ReleaseJavaClassDescriptor(cx, jEnv, java_wrapper->class_descriptor);            JS_free(cx, java_wrapper);            jsj_ExitJava(jsj_env);        } else {            java_wrapper->u.next = deferred_wrappers;            deferred_wrappers = java_wrapper;        }    }}/* Trivial helper for jsj_DiscardJavaObjReflections(), below */static JSIntnenumerate_remove_java_obj(JSJHashEntry *he, JSIntn i, void *arg){    JSJavaThreadState *jsj_env = (JSJavaThreadState *)arg;    JNIEnv *jEnv = jsj_env->jEnv;    jobject java_obj;    JavaObjectWrapper *java_wrapper;    JSObject *java_wrapper_obj;    java_wrapper_obj = (JSObject *)he->value;    /* Warning: NULL argument may cause assertion in JS engine, but it's actually OK */    java_wrapper = JS_GetPrivate(jsj_env->cx, java_wrapper_obj);    java_obj = java_wrapper->java_obj;    (*jEnv)->DeleteGlobalRef(jEnv, java_obj);    java_wrapper->java_obj = NULL;    return HT_ENUMERATE_REMOVE;}/* This shutdown routine discards all JNI references to Java objects   that have been reflected into JS, even if there are still references   to them from JS. */voidjsj_DiscardJavaObjReflections(JNIEnv *jEnv){    JSJavaThreadState *jsj_env;    char *err_msg;    /* Get the per-thread state corresponding to the current Java thread */    jsj_env = jsj_MapJavaThreadToJSJavaThreadState(jEnv, &err_msg);    JS_ASSERT(jsj_env);    if (!jsj_env)        return;    if (java_obj_reflections) {        JSJ_HashTableEnumerateEntries(java_obj_reflections,                                      enumerate_remove_java_obj,                                      (void*)jsj_env);        JSJ_HashTableDestroy(java_obj_reflections);        java_obj_reflections = NULL;    }}JSBool JS_DLL_CALLBACK

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -