Add Class::IsFinalizable and Object::AddFinalizerReference.
Also correctly set the special bit in Class' flags.
We need compiler support before I can go further.
Change-Id: Ib7a637d7140a6f8c416635738d4d0b57c17ad628
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 1049107..6ebc638 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -470,7 +470,7 @@
}
// Let the heap know some key offsets into java.lang.ref instances
- // NB we hard code the field indexes here rather than using FindInstanceField
+ // Note: we hard code the field indexes here rather than using FindInstanceField
// as the types of the field can't be resolved prior to the runtime being
// fully initialized
Class* java_lang_ref_Reference = FindSystemClass("Ljava/lang/ref/Reference;");
@@ -1053,16 +1053,32 @@
Method* dst) {
const DexFile::MethodId& method_id = dex_file.GetMethodId(src.method_idx_);
dst->SetDeclaringClass(klass);
+
String* method_name = ResolveString(dex_file, method_id.name_idx_, klass->GetDexCache());
dst->SetName(method_name);
if (method_name->Equals("<init>")) {
dst->SetClass(GetClassRoot(kJavaLangReflectConstructor));
}
- {
- int32_t utf16_length;
- std::string utf8(dex_file.CreateMethodDescriptor(method_id.proto_idx_, &utf16_length));
- dst->SetSignature(intern_table_->InternStrong(utf16_length, utf8.c_str()));
+
+ int32_t utf16_length;
+ std::string signature(dex_file.CreateMethodDescriptor(method_id.proto_idx_, &utf16_length));
+ dst->SetSignature(intern_table_->InternStrong(utf16_length, signature.c_str()));
+
+ if (method_name->Equals("finalize") && signature == "()V") {
+ /*
+ * The Enum class declares a "final" finalize() method to prevent subclasses from introducing
+ * a finalizer. We don't want to set the finalizable flag for Enum or its subclasses, so we
+ * exclude it here.
+ *
+ * We also want to avoid setting the flag on Object, where we know that finalize() is empty.
+ */
+ if (klass->GetClassLoader() != NULL ||
+ (!klass->GetDescriptor()->Equals("Ljava/lang/Object;") &&
+ !klass->GetDescriptor()->Equals("Ljava/lang/Enum;"))) {
+ klass->SetFinalizable();
+ }
}
+
dst->SetProtoIdx(method_id.proto_idx_);
dst->SetCodeItemOffset(src.code_off_);
const char* shorty = dex_file.GetShorty(method_id.proto_idx_);
@@ -1771,7 +1787,6 @@
"java.lang.Object must not have a superclass");
return false;
}
- // TODO: clear finalize attribute
return true;
}
if (super == NULL) {
@@ -1795,6 +1810,12 @@
PrettyDescriptor(klass->GetDescriptor()).c_str());
return false;
}
+
+ // Inherit kAccClassIsFinalizable from the superclass in case this class doesn't override finalize.
+ if (super->IsFinalizable()) {
+ klass->SetFinalizable();
+ }
+
#ifndef NDEBUG
// Ensure super classes are fully resolved prior to resolving fields..
while (super != NULL) {