commonref.c

来自「This is a resource based on j2me embedde」· C语言 代码 · 共 610 行 · 第 1/2 页

C
610
字号
/* * @(#)commonRef.c	1.24 06/10/25 * * Copyright  1990-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER *  * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 only, as published by the Free Software Foundation.  *  * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License version 2 for more details (a copy is * included at /legal/license.txt).  *  * You should have received a copy of the GNU General Public License * version 2 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA  *  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.com if you need additional * information or have any questions.  */#include "util.h"#include "commonRef.h"#define ALL_REFS -1/* * Each object sent to the front end is tracked with the RefNode struct  * (see util.h). * External to this module, objects are identified by a jlong id which is  * simply the sequence number. A weak reference is usually used so that * the presence of a debugger-tracked object will not prevent * its collection. Once an object is collected, its RefNode may be  * deleted and the weak ref inside may be reused (these may happen in * either order). Using the sequence number * as the object id prevents ambiguity in the object id when the weak ref  * is reused. The RefNode* is stored with the object as it's JVMTI Tag. * * The ref member is changed from weak to strong when * gc of the object is to be prevented. * Whether or not it is strong, it is never exported from this module. * * A reference count of each jobject is also maintained here. It tracks * the number times an object has been referenced through  * commonRef_refToID. A RefNode is freed once the reference * count is decremented to 0 (with commonRef_release*), even if the  * correspoding object has not been collected. * * One hash table is maintained. The mapping of ID to jobject (or RefNode*) * is handled with one hash table that will re-size itself as the number * of RefNode's grow. *//* Initial hash table size (must be power of 2) */#define HASH_INIT_SIZE 512/* If element count exceeds HASH_EXPAND_SCALE*hash_size we expand & re-hash */#define HASH_EXPAND_SCALE 8/* Maximum hash table size (must be power of 2) */#define HASH_MAX_SIZE  (1024*HASH_INIT_SIZE)/* Map a key (ID) to a hash bucket */static jint hashBucket(jlong key) {    /* Size should always be a power of 2, use mask instead of mod operator */    /*LINTED*/    return ((jint)key) & (gdata->objectsByIDsize-1);}/* Generate a new ID */static jlong newSeqNum(void){    return gdata->nextSeqNum++;}/* Create a fresh RefNode structure, create a weak ref and tag the object */static RefNode *createNode(JNIEnv *env, jobject ref) {    RefNode   *node;    jobject    weakRef;    jvmtiError error;      /* Could allocate RefNode's in blocks, not sure it would help much */    node = (RefNode*)jvmtiAllocate((int)sizeof(RefNode));         if (node == NULL) {        return NULL;    }        /* Create weak reference to make sure we have a reference */    weakRef = JNI_FUNC_PTR(env,NewWeakGlobalRef)(env, ref);    if (weakRef == NULL) {        jvmtiDeallocate(node);        return NULL;    }    /* Set tag on weakRef */    error = JVMTI_FUNC_PTR(gdata->jvmti, SetTag)                          (gdata->jvmti, weakRef, (jlong)((jint)node));    if ( error != JVMTI_ERROR_NONE ) {        JNI_FUNC_PTR(env,DeleteWeakGlobalRef)(env, weakRef);        jvmtiDeallocate(node);        return NULL;    }    /* Fill in RefNode */    node->ref      = weakRef;    node->isStrong = JNI_FALSE;    node->count    = 1;    node->seqNum   = newSeqNum();    /* Count RefNode's created */    gdata->objectsByIDcount++;    return node;}/* Delete a RefNode allocation, delete weak/global ref and clear tag */static void deleteNode(JNIEnv *env, RefNode *node){    LOG_MISC(("Freeing %d (%x)\n", (int)node->seqNum, node->ref));    if ( node->ref != NULL ) {        /* Clear tag */        (void)JVMTI_FUNC_PTR(gdata->jvmti,SetTag)                            (gdata->jvmti, node->ref, NULL_OBJECT_ID);        if (node->isStrong) {            JNI_FUNC_PTR(env,DeleteGlobalRef)(env, node->ref);        } else {            JNI_FUNC_PTR(env,DeleteWeakGlobalRef)(env, node->ref);        }    }    gdata->objectsByIDcount--;    jvmtiDeallocate(node);}/* Change a RefNode to have a strong reference */static jobjectstrengthenNode(JNIEnv *env, RefNode *node) {    if (!node->isStrong) {        jobject strongRef;                strongRef = JNI_FUNC_PTR(env,NewGlobalRef)(env, node->ref);        /*         * NewGlobalRef on a weak ref will return NULL if the weak          * reference has been collected or if out of memory.          * We need to distinguish those two occurrences.         */        if ((strongRef == NULL) && !isSameObject(env, node->ref, NULL)) {            EXIT_ERROR(AGENT_ERROR_NULL_POINTER,"NewGlobalRef");        }         if (strongRef != NULL) {            JNI_FUNC_PTR(env,DeleteWeakGlobalRef)(env, node->ref);            node->ref      = strongRef;            node->isStrong = JNI_TRUE;         }        return strongRef;    } else {        return node->ref;    }}/* Change a RefNode to have a weak reference */static jweakweakenNode(JNIEnv *env, RefNode *node) {    if (node->isStrong) {        jweak weakRef;                weakRef = JNI_FUNC_PTR(env,NewWeakGlobalRef)(env, node->ref);        if (weakRef != NULL) {            JNI_FUNC_PTR(env,DeleteGlobalRef)(env, node->ref);            node->ref      = weakRef;            node->isStrong = JNI_FALSE;        }        return weakRef;    } else {        return node->ref;    }}/* * Returns the node which contains the common reference for the  * given object. The passed reference should not be a weak reference * managed in the object hash table (i.e. returned by commonRef_idToRef) * because no sequence number checking is done. */static RefNode *findNodeByRef(JNIEnv *env, jobject ref) {    jvmtiError error;    jlong      tag;    tag   = NULL_OBJECT_ID;    error = JVMTI_FUNC_PTR(gdata->jvmti,GetTag)(gdata->jvmti, ref, &tag);    if ( error == JVMTI_ERROR_NONE ) {        RefNode   *node;                node = (RefNode*)((jint)tag);        return node;    }    return NULL;}/* Locate and delete a node based on ID */static void deleteNodeByID(JNIEnv *env, jlong id, jint refCount) {    jint     slot;    RefNode *node;    RefNode *prev;        slot = hashBucket(id);    node = gdata->objectsByID[slot];    prev = NULL;    while (node != NULL) {        if (id == node->seqNum) {            if (refCount != ALL_REFS) {                node->count -= refCount;            } else {                node->count = 0;            }            if (node->count <= 0) {                if ( node->count < 0 ) {                    EXIT_ERROR(AGENT_ERROR_INTERNAL,"RefNode count < 0");                }                /* Detach from id hash table */                if (prev == NULL) {                    gdata->objectsByID[slot] = node->next;                } else {                    prev->next = node->next;                }                deleteNode(env, node);            }            break;        }        prev = node;        node = node->next;    }}/* * Returns the node stored in the object hash table for the given object * id. The id should be a value previously returned by  * commonRef_refToID. * *  NOTE: It is possible that a match is found here, but that the object *        is garbage collected by the time the caller inspects node->ref. *        Callers should take care using the node->ref object returned here. * */static RefNode *findNodeByID(JNIEnv *env, jlong id) {    jint     slot;    RefNode *node;    RefNode *prev;    slot = hashBucket(id);    node = gdata->objectsByID[slot];    prev = NULL;    while (node != NULL) {        if ( id == node->seqNum ) {            if ( prev != NULL ) {                /* Re-order hash list so this one is up front */                prev->next = node->next;                node->next = gdata->objectsByID[slot];                gdata->objectsByID[slot] = node;            }            break;        }        node = node->next;    }    return node;}/* Initialize the hash table stored in gdata area */static void initializeObjectsByID(int size) {    /* Size should always be a power of 2 */    if ( size > HASH_MAX_SIZE ) size = HASH_MAX_SIZE;    gdata->objectsByIDsize  = size;    gdata->objectsByIDcount = 0;    gdata->objectsByID      = (RefNode**)jvmtiAllocate((int)sizeof(RefNode*)*size);    (void)memset(gdata->objectsByID, 0, (int)sizeof(RefNode*)*size);}/* hash in a RefNode */static voidhashIn(RefNode *node){    jint     slot;        /* Add to id hashtable */    slot                     = hashBucket(node->seqNum);

⌨️ 快捷键说明

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