Avoid a case of eager initialization.
Don't mark as initialized classes that contain static field
initialization.
Change-Id: Iedcabbdf355e8861eb7731650eee1467f68ae0cd
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 80dd7eb..c94347d 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -546,7 +546,7 @@
for (size_t i = 0; i < ClassLinker::kClassRootsMax; ++i) {
Class* c = GetClassRoot(ClassRoot(i));
if (!c->IsArrayClass() && !c->IsPrimitive()) {
- EnsureInitialized(GetClassRoot(ClassRoot(i)), true);
+ EnsureInitialized(GetClassRoot(ClassRoot(i)), true, true);
CHECK(!self->IsExceptionPending()) << PrettyTypeOf(self->GetException());
}
}
@@ -2338,7 +2338,7 @@
CHECK_EQ(mh.GetReturnType(), mh2.GetReturnType());
}
-bool ClassLinker::InitializeClass(Class* klass, bool can_run_clinit) {
+bool ClassLinker::InitializeClass(Class* klass, bool can_run_clinit, bool can_init_statics) {
CHECK(klass->IsResolved() || klass->IsErroneous())
<< PrettyClass(klass) << " is " << klass->GetStatus();
@@ -2404,7 +2404,7 @@
uint64_t t0 = NanoTime();
- if (!InitializeSuperClass(klass, can_run_clinit)) {
+ if (!InitializeSuperClass(klass, can_run_clinit, can_init_statics)) {
// Super class initialization failed, this can be because we can't run
// super-class class initializers in which case we'll be verified.
// Otherwise this class is erroneous.
@@ -2416,7 +2416,7 @@
return false;
}
- InitializeStaticFields(klass);
+ bool has_static_field_initializers = InitializeStaticFields(klass);
if (clinit != NULL) {
clinit->Invoke(self, NULL, NULL, NULL);
@@ -2441,7 +2441,14 @@
++thread_stats->class_init_count;
global_stats->class_init_time_ns += (t1 - t0);
thread_stats->class_init_time_ns += (t1 - t0);
- klass->SetStatus(Class::kStatusInitialized);
+ // Set the class as initialized except if we can't initialize static fields and static field
+ // initialization is necessary.
+ if (!can_init_statics && has_static_field_initializers) {
+ klass->SetStatus(Class::kStatusVerified); // Don't leave class in initializing state.
+ success = false;
+ } else {
+ klass->SetStatus(Class::kStatusInitialized);
+ }
if (VLOG_IS_ON(class_linker)) {
ClassHelper kh(klass);
LOG(INFO) << "Initialized class " << kh.GetDescriptor() << " from " << kh.GetLocation();
@@ -2577,7 +2584,7 @@
return found1 == found2;
}
-bool ClassLinker::InitializeSuperClass(Class* klass, bool can_run_clinit) {
+bool ClassLinker::InitializeSuperClass(Class* klass, bool can_run_clinit, bool can_init_fields) {
CHECK(klass != NULL);
if (!klass->IsInterface() && klass->HasSuperClass()) {
Class* super_class = klass->GetSuperClass();
@@ -2585,7 +2592,7 @@
CHECK(!super_class->IsInterface());
Thread* self = Thread::Current();
klass->MonitorEnter(self);
- bool super_initialized = InitializeClass(super_class, can_run_clinit);
+ bool super_initialized = InitializeClass(super_class, can_run_clinit, can_init_fields);
klass->MonitorExit(self);
// TODO: check for a pending exception
if (!super_initialized) {
@@ -2604,7 +2611,7 @@
return true;
}
-bool ClassLinker::EnsureInitialized(Class* c, bool can_run_clinit) {
+bool ClassLinker::EnsureInitialized(Class* c, bool can_run_clinit, bool can_init_fields) {
CHECK(c != NULL);
if (c->IsInitialized()) {
return true;
@@ -2612,7 +2619,7 @@
Thread* self = Thread::Current();
ScopedThreadStateChange tsc(self, Thread::kRunnable);
- bool success = InitializeClass(c, can_run_clinit);
+ bool success = InitializeClass(c, can_run_clinit, can_init_fields);
if (!success) {
CHECK(self->IsExceptionPending() || !can_run_clinit) << PrettyClass(c);
}
@@ -2629,15 +2636,15 @@
}
}
-void ClassLinker::InitializeStaticFields(Class* klass) {
+bool ClassLinker::InitializeStaticFields(Class* klass) {
size_t num_static_fields = klass->NumStaticFields();
if (num_static_fields == 0) {
- return;
+ return false;
}
DexCache* dex_cache = klass->GetDexCache();
// TODO: this seems like the wrong check. do we really want !IsPrimitive && !IsArray?
if (dex_cache == NULL) {
- return;
+ return false;
}
ClassHelper kh(klass);
const DexFile::ClassDef* dex_class_def = kh.GetClassDef();
@@ -2652,7 +2659,9 @@
for (size_t i = 0; it.HasNext(); i++, it.Next()) {
it.ReadValueToField(field_map[i]);
}
+ return true;
}
+ return false;
}
bool ClassLinker::LinkClass(SirtRef<Class>& klass, ObjectArray<Class>* interfaces) {