summaryrefslogtreecommitdiff
path: root/runtime/class_linker.cc
diff options
context:
space:
mode:
author Vladimir Marko <vmarko@google.com> 2024-03-28 14:52:57 +0000
committer VladimĂ­r Marko <vmarko@google.com> 2024-03-28 17:27:48 +0000
commit3cf63ff47617fff6ea9480a22513d89f230ccc15 (patch)
tree923cfc5810261b98f14f528c87aa48375b1e9f64 /runtime/class_linker.cc
parent5344ecaf0fb14e870f9a5910ead528179c5d9493 (diff)
Simplify finalizer check in `ClassLinker::LoadMethod()`.
Move the special handling for `Object` and `Enum` to the `ClassLinker::InitWithoutImage()` to simplify the function used for loading methods for all classes. Test: test-art-host-gtest Test: testrunner.py --host --optimizing Bug: 329196666 Change-Id: I81057802dfa6406045deea53c8029de3622a9ef8
Diffstat (limited to 'runtime/class_linker.cc')
-rw-r--r--runtime/class_linker.cc34
1 files changed, 17 insertions, 17 deletions
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 4c1abedc99..9d405207a5 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -865,8 +865,13 @@ bool ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b
}
// Object, String, ClassExt and DexCache need to be rerun through FindSystemClass to finish init
+ // We also need to immediately clear the finalizable flag for Object so that other classes are
+ // not erroneously marked as finalizable. (Object defines an empty finalizer, so that other
+ // classes can override it but it is not itself finalizable.)
mirror::Class::SetStatus(java_lang_Object, ClassStatus::kNotReady, self);
CheckSystemClass(self, java_lang_Object, "Ljava/lang/Object;");
+ CHECK(java_lang_Object->IsFinalizable());
+ java_lang_Object->ClearFinalizable();
CHECK_EQ(java_lang_Object->GetObjectSize(), mirror::Object::InstanceSize());
mirror::Class::SetStatus(java_lang_String, ClassStatus::kNotReady, self);
CheckSystemClass(self, java_lang_String, "Ljava/lang/String;");
@@ -914,6 +919,14 @@ bool ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b
CHECK_EQ(object_array_string.Get(),
FindSystemClass(self, GetClassRootDescriptor(ClassRoot::kJavaLangStringArrayClass)));
+ // The Enum class declares a "final" finalize() method to prevent subclasses from introducing
+ // a finalizer but it is not itself consedered finalizable. Load the Enum class now and clear
+ // the finalizable flag to prevent subclasses from being marked as finalizable.
+ CHECK_EQ(LookupClass(self, "Ljava/lang/Enum;", /*class_loader=*/ nullptr), nullptr);
+ Handle<mirror::Class> java_lang_Enum = hs.NewHandle(FindSystemClass(self, "Ljava/lang/Enum;"));
+ CHECK(java_lang_Enum->IsFinalizable());
+ java_lang_Enum->ClearFinalizable();
+
// End of special init trickery, all subsequent classes may be loaded via FindSystemClass.
// Create java.lang.reflect.Proxy root.
@@ -4007,24 +4020,11 @@ void ClassLinker::LoadMethod(const DexFile& dex_file,
memcmp(ascii_name, method_name, length) == 0;
};
if (UNLIKELY(has_ascii_name("finalize", sizeof("finalize") - 1u))) {
- // Set finalizable flag on declaring class.
+ // Set finalizable flag on declaring class if the method has the right signature.
+ // When initializing without a boot image, `Object` and `Enum` shall have the finalizable
+ // flag cleared immediately after loading these classes, see `InitWithoutImage()`.
if (shorty == "V") {
- // Void return type.
- if (klass->GetClassLoader() != nullptr) { // All non-boot finalizer methods are flagged.
- klass->SetFinalizable();
- } else {
- std::string_view klass_descriptor =
- dex_file.GetTypeDescriptorView(dex_file.GetTypeId(klass->GetDexTypeIndex()));
- // 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_descriptor != "Ljava/lang/Object;" &&
- klass_descriptor != "Ljava/lang/Enum;") {
- klass->SetFinalizable();
- }
- }
+ klass->SetFinalizable();
}
} else if (method_name[0] == '<') {
// Fix broken access flags for initializers. Bug 11157540.