Example #1
0
static void finalizeObject(Env* env, Object* obj) {
//    TRACEF("finalizeObject: %p (%s)\n", obj, obj->clazz->name);

    rvmLockMutex(&referentsLock);
    void* key = (void*) GC_HIDE_POINTER(obj);
    ReferentEntry* referentEntry;
    HASH_FIND_PTR(referents, &key, referentEntry);

    assert(referentEntry != NULL);

    if (referentEntry->references == NULL) {
        // The object is not referenced by any type of reference and can never be resurrected.
        HASH_DEL(referents, referentEntry);
        rvmUnlockMutex(&referentsLock);
        return;
    }

    Object* softReferences = NULL;
    Object* weakReferences = NULL;
    Object* finalizerReferences = NULL;
    Object* phantomReferences = NULL;
    Object* clearedReferences = NULL;

    ReferenceList* refNode;
    while (referentEntry->references != NULL) {
        refNode = referentEntry->references;
        LL_DELETE(referentEntry->references, refNode);
        Object** list = NULL;
        Object* reference = refNode->reference;
        if (rvmIsSubClass(java_lang_ref_SoftReference, reference->clazz)) {
            list = &softReferences;
        } else if (rvmIsSubClass(java_lang_ref_WeakReference, reference->clazz)) {
            list = &weakReferences;
        } else if (rvmIsSubClass(java_lang_ref_FinalizerReference, reference->clazz)) {
            list = &finalizerReferences;
        } else if (rvmIsSubClass(java_lang_ref_PhantomReference, reference->clazz)) {
            list = &phantomReferences;
        }
        enqueuePendingReference(env, reference, list);
    }
    assert(referentEntry->references == NULL);

    clearAndEnqueueReferences(env, &softReferences, &clearedReferences);
    clearAndEnqueueReferences(env, &weakReferences, &clearedReferences);
    enqueueFinalizerReferences(env, &finalizerReferences, &clearedReferences);
    clearAndEnqueueReferences(env, &phantomReferences, &clearedReferences);

    // Reregister for finalization. If no new references have been added to the list of references for the referent the
    // next time it gets finalized we know it will never be resurrected.
    GC_REGISTER_FINALIZER_NO_ORDER(obj, _finalizeObject, NULL, NULL, NULL);

    rvmUnlockMutex(&referentsLock);

    if (clearedReferences != NULL) {
        rvmCallVoidClassMethod(env, java_lang_ref_ReferenceQueue, java_lang_ref_ReferenceQueue_add, clearedReferences);
        assert(rvmExceptionOccurred(env) == NULL);
    }
}
Example #2
0
void rvmRegisterReference(Env* env, Object* reference, Object* referent) {
    if (referent) {
        // Add 'reference' to the references list for 'referent' in the referents hashtable
        rvmLockMutex(&referentsLock);

        ReferenceList* l = rvmAllocateMemory(env, sizeof(ReferenceList));
        if (!l) goto done; // OOM thrown
        l->reference = reference;

        void* key = (void*) GC_HIDE_POINTER(referent); // Hide the pointer from the GC so that it doesn't prevent the referent from being GCed.
        ReferentEntry* referentEntry;
        HASH_FIND_PTR(referents, &key, referentEntry);
        if (!referentEntry) {
            // referent is not in the hashtable. Add it.
            referentEntry = rvmAllocateMemory(env, sizeof(ReferentEntry));
            if (!referentEntry) goto done; // OOM thrown
            referentEntry->key = key;
            HASH_ADD_PTR(referents, key, referentEntry);
        }

        // Add the reference to the referent's list of references
        LL_PREPEND(referentEntry->references, l);

        // Register the referent for finalization
        GC_REGISTER_FINALIZER_NO_ORDER(referent, _finalizeObject, NULL, NULL, NULL);

done:
        rvmUnlockMutex(&referentsLock);
    }
}
Example #3
0
jboolean rvmAddObjectGCRoot(Env* env, Object* object) {
    rvmLockMutex(&gcRootsLock);
    jboolean r = addObjectGCRoot(env, object, (void***) &objectGCRoots, &objectGCRootsCount, 
                    &objectGCRootsSize, OBJECTS_GC_ROOTS_INITIAL_SIZE);
    rvmUnlockMutex(&gcRootsLock);
    return r;
}
Example #4
0
void registerCleanupHandler(Env* env, Object* object, CleanupHandler handler) {
    rvmLockMutex(&referentsLock);
    CleanupHandlerList* l = rvmAllocateMemory(env, sizeof(CleanupHandlerList));
    if (!l) goto done; // OOM thrown
    l->handler = handler;
    ReferentEntry* referentEntry = getReferentEntryForObject(env, object);
    if (!referentEntry) goto done;
    // Add the handler to the object's list of cleanup handlers
    LL_PREPEND(referentEntry->cleanupHandlers, l);
    // Register the referent for finalization
    GC_REGISTER_FINALIZER_NO_ORDER(object, _finalizeObject, NULL, NULL, NULL);

done:
    rvmUnlockMutex(&referentsLock);
}
Example #5
0
void rvmRegisterReference(Env* env, Object* reference, Object* referent) {
    if (referent) {
        // Add 'reference' to the references list for 'referent' in the referents hashtable
        rvmLockMutex(&referentsLock);

        ReferenceList* l = rvmAllocateMemory(env, sizeof(ReferenceList));
        if (!l) goto done; // OOM thrown
        l->reference = reference;
        ReferentEntry* referentEntry = getReferentEntryForObject(env, referent);
        if (!referentEntry) goto done;
        // Add the reference to the referent's list of references
        LL_PREPEND(referentEntry->references, l);
        // Register the referent for finalization
        GC_REGISTER_FINALIZER_NO_ORDER(referent, _finalizeObject, NULL, NULL, NULL);

done:
        rvmUnlockMutex(&referentsLock);
    }
}
Example #6
0
static inline void releaseThreadStackTraceLock() {
    rvmUnlockMutex(&threadStackTraceLock);
}
Example #7
0
static inline void releaseNativeLibsLock() {
    rvmUnlockMutex(&nativeLibsLock);
}
Example #8
0
inline void rvmUnlockThreadsList() {
    rvmUnlockMutex(&threadsLock);
}
Example #9
0
static inline void releaseInternedStringsLock() {
    rvmUnlockMutex(&internedStringsLock);
}
Example #10
0
static inline void releaseClassLock() {
    rvmUnlockMutex(&classLock);
}