/* * Adds a reference to the tail of a circular queue of references. */ static void enqueuePendingReference(Env* env, Object* ref, Object** list) { // This code is a port of the enqueuePendingReference() function in Android's MarkSweep.cpp if (*list == NULL) { // ref.pendingNext = ref rvmSetObjectInstanceFieldValue(env, ref, java_lang_ref_Reference_pendingNext, ref); *list = ref; } else { // head = list.pendingNext Object* head = rvmGetObjectInstanceFieldValue(env, *list, java_lang_ref_Reference_pendingNext); // ref.pendingNext = head rvmSetObjectInstanceFieldValue(env, ref, java_lang_ref_Reference_pendingNext, head); // list.pendingNext = ref rvmSetObjectInstanceFieldValue(env, *list, java_lang_ref_Reference_pendingNext, ref); } }
/* * Removes the reference at the head of a circular queue of * references. */ static Object* dequeuePendingReference(Env* env, Object** list) { // This code is a port of the dequeuePendingReference() function in Android's MarkSweep.cpp assert(list != NULL); assert(*list != NULL); // head = list.pendingNext Object* head = rvmGetObjectInstanceFieldValue(env, *list, java_lang_ref_Reference_pendingNext); Object* ref; if (*list == head) { ref = *list; *list = NULL; } else { // next = head.pendingNext Object* next = rvmGetObjectInstanceFieldValue(env, head, java_lang_ref_Reference_pendingNext); // list.pendingNext = next rvmSetObjectInstanceFieldValue(env, *list, java_lang_ref_Reference_pendingNext, next); ref = head; } rvmSetObjectInstanceFieldValue(env, ref, java_lang_ref_Reference_pendingNext, NULL); return ref; }
/* * Enqueues finalizer references with unreachable referents. The * referent is moved to the zombie field (which makes it reachable again), * and the referent field is cleared. */ static void enqueueFinalizerReferences(Env* env, Object** list, Object** cleared) { // This code is a port of the enqueueFinalizerReferences() function in Android's MarkSweep.cpp assert(list != NULL); while (*list != NULL) { Object* ref = dequeuePendingReference(env, list); Object* referent = rvmGetObjectInstanceFieldValue(env, ref, java_lang_ref_Reference_referent); if (referent != NULL) { /* If the referent is non-null the reference must queuable. */ assert(isEnqueuable(env, ref)); // Copy the referent to the zombie field rvmSetObjectInstanceFieldValue(env, ref, java_lang_ref_FinalizerReference_zombie, referent); // Clear the referent clearReference(env, ref); enqueueReference(env, ref, cleared); } } assert(*list == NULL); }
/* * Clear the referent field. */ static void clearReference(Env* env, Object* reference) { // This code is a port of the clearReference() function in Android's MarkSweep.cpp rvmSetObjectInstanceFieldValue(env, reference, java_lang_ref_Reference_referent, NULL); }
static jboolean getAnnotationValue(Env* env, void** attributes, Class* expectedAnnotationClass, Object* classLoader, jvalue* result, jboolean ignoreClassNotFound) { char* annotationTypeName = getString(attributes); if (expectedAnnotationClass && strncmp(&annotationTypeName[1], expectedAnnotationClass->name, strlen(expectedAnnotationClass->name))) { return throwFormatError(env, rvmFromBinaryClassName(env, expectedAnnotationClass->name)); } Class* annotationClass = expectedAnnotationClass; if (!annotationClass) { annotationClass = rvmFindClassByDescriptor(env, annotationTypeName, classLoader); if (!annotationClass) { if (ignoreClassNotFound && rvmExceptionOccurred(env)->clazz == java_lang_ClassNotFoundException) { rvmExceptionClear(env); jint length = getInt(attributes); for (jint i = 0; i < length; i++) { getString(attributes); skipElementValue(attributes); } } return FALSE; } } // Find the annotation impl class Class* annotationImplClass = findAnnotationImplClass(env, annotationClass, classLoader); if (rvmExceptionCheck(env)) return FALSE; jint length = getInt(attributes); if (length == 0) { // No member values specified. Use a singleton instance. Method* factoryMethod = rvmGetClassMethod(env, annotationImplClass, "$createSingleton", "()Ljava/lang/Object;"); if (rvmExceptionCheck(env)) return FALSE; Object* annotationObject = rvmCallObjectClassMethod(env, annotationImplClass, factoryMethod); if (rvmExceptionCheck(env)) return FALSE; result->l = (jobject) annotationObject; return TRUE; } // Call the annotation impl $create() method Method* factoryMethod = rvmGetClassMethod(env, annotationImplClass, "$create", "()Ljava/lang/Object;"); if (rvmExceptionCheck(env)) return FALSE; Object* annotationObject = rvmCallObjectClassMethod(env, annotationImplClass, factoryMethod); if (rvmExceptionCheck(env)) return FALSE; jint i = 0; for (i = 0; i < length; i++) { char* name = getString(attributes); Method* method = getAnnotationValueMethod(env, annotationClass, name); if (rvmExceptionCheck(env)) return FALSE; if (!method) { skipElementValue(attributes); } else { const char* memberDesc = rvmGetReturnType(method->desc); Class* type = findType(env, memberDesc, method->clazz->classLoader); Object* value = NULL; if (!type) { value = rvmExceptionClear(env); } else { jvalue v = {0}; if (!parseElementValue(env, attributes, type, classLoader, &v)) { value = rvmExceptionClear(env); } else { value = rvmBox(env, type, &v); } } InstanceField* field = getAnnotationMemberField(env, annotationImplClass, method->name); if (!field) return FALSE; rvmSetObjectInstanceFieldValue(env, annotationObject, field, value); if (rvmExceptionCheck(env)) return FALSE; } } result->l = (jobject) annotationObject; return TRUE; }
static void SetObjectField(JNIEnv* env, jobject obj, jfieldID fieldID, jobject val) { rvmSetObjectInstanceFieldValue((Env*) env, (Object*) obj, (InstanceField*) fieldID, (Object*) val); }