加载 - 链接(验证,准备,解析)- 初始化 - 使用 - 卸载
1 | ClassStatus: uint8_t { |
kNotReady - kIdx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21void ClassLinker::SetupClass(const DexFile& dex_file,
const dex::ClassDef& dex_class_def,
Handle<mirror::Class> klass,
ObjPtr<mirror::ClassLoader> class_loader) {
CHECK(klass != nullptr);
CHECK(klass->GetDexCache() != nullptr);
CHECK_EQ(ClassStatus::kNotReady, klass->GetStatus()); // 校验是否kNotReady
const char* descriptor = dex_file.GetClassDescriptor(dex_class_def);
CHECK(descriptor != nullptr);
//给Class赋值
klass->SetClass(GetClassRoot<mirror::Class>(this));
uint32_t access_flags = dex_class_def.GetJavaAccessFlags();
CHECK_EQ(access_flags & ~kAccJavaFlagsMask, 0U);
klass->SetAccessFlags(access_flags);
klass->SetClassLoader(class_loader);
DCHECK_EQ(klass->GetPrimitiveType(), Primitive::kPrimNot);
mirror::Class::SetStatus(klass, ClassStatus::kIdx, nullptr); // 设置为kIdx
klass->SetDexClassDefIndex(dex_file.GetIndexForClassDef(dex_class_def));
klass->SetDexTypeIndex(dex_class_def.class_idx_);
}kIdx - kLoaded
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62LoadClass(self, *new_dex_file, *new_class_def, klass);
bool ClassLinker::LoadSuperAndInterfaces(Handle<mirror::Class> klass, const DexFile& dex_file) {
CHECK_EQ(ClassStatus::kIdx, klass->GetStatus());
const dex::ClassDef& class_def = dex_file.GetClassDef(klass->GetDexClassDefIndex());
dex::TypeIndex super_class_idx = class_def.superclass_idx_;
if (super_class_idx.IsValid()) {
// Check that a class does not inherit from itself directly.
//
// TODO: This is a cheap check to detect the straightforward case
// of a class extending itself (b/28685551), but we should do a
// proper cycle detection on loaded classes, to detect all cases
// of class circularity errors (b/28830038).
if (super_class_idx == class_def.class_idx_) {
ThrowClassCircularityError(klass.Get(),
"Class %s extends itself",
klass->PrettyDescriptor().c_str());
return false;
}
ObjPtr<mirror::Class> super_class = ResolveType(super_class_idx, klass.Get());
if (super_class == nullptr) {
DCHECK(Thread::Current()->IsExceptionPending());
return false;
}
// Verify
if (!klass->CanAccess(super_class)) {
ThrowIllegalAccessError(klass.Get(), "Class %s extended by class %s is inaccessible",
super_class->PrettyDescriptor().c_str(),
klass->PrettyDescriptor().c_str());
return false;
}
CHECK(super_class->IsResolved());
klass->SetSuperClass(super_class);
}
const dex::TypeList* interfaces = dex_file.GetInterfacesList(class_def);
if (interfaces != nullptr) {
for (size_t i = 0; i < interfaces->Size(); i++) {
dex::TypeIndex idx = interfaces->GetTypeItem(i).type_idx_;
ObjPtr<mirror::Class> interface = ResolveType(idx, klass.Get());
if (interface == nullptr) {
DCHECK(Thread::Current()->IsExceptionPending());
return false;
}
// Verify
if (!klass->CanAccess(interface)) {
// TODO: the RI seemed to ignore this in my testing.
ThrowIllegalAccessError(klass.Get(),
"Interface %s implemented by class %s is inaccessible",
interface->PrettyDescriptor().c_str(),
klass->PrettyDescriptor().c_str());
return false;
}
}
}
// Mark the class as loaded.
mirror::Class::SetStatus(klass, ClassStatus::kLoaded, nullptr); // 设置加载完成的标记
return true;
}kLoaded - kResolving - kResolved
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143bool ClassLinker::LinkClass(Thread* self,
const char* descriptor,
Handle<mirror::Class> klass,
Handle<mirror::ObjectArray<mirror::Class>> interfaces,
MutableHandle<mirror::Class>* h_new_class_out) {
CHECK_EQ(ClassStatus::kLoaded, klass->GetStatus());
if (!LinkSuperClass(klass)) {
return false;
}
ArtMethod* imt_data[ImTable::kSize];
// If there are any new conflicts compared to super class.
bool new_conflict = false;
std::fill_n(imt_data, arraysize(imt_data), Runtime::Current()->GetImtUnimplementedMethod());
if (!LinkMethods(self, klass, interfaces, &new_conflict, imt_data)) {
return false;
}
if (!LinkInstanceFields(self, klass)) {
return false;
}
size_t class_size;
if (!LinkStaticFields(self, klass, &class_size)) {
return false;
}
CreateReferenceInstanceOffsets(klass);
CHECK_EQ(ClassStatus::kLoaded, klass->GetStatus());
ImTable* imt = nullptr;
if (klass->ShouldHaveImt()) {
// If there are any new conflicts compared to the super class we can not make a copy. There
// can be cases where both will have a conflict method at the same slot without having the same
// set of conflicts. In this case, we can not share the IMT since the conflict table slow path
// will possibly create a table that is incorrect for either of the classes.
// Same IMT with new_conflict does not happen very often.
if (!new_conflict) {
ImTable* super_imt = FindSuperImt(klass.Get(), image_pointer_size_);
if (super_imt != nullptr) {
bool imt_equals = true;
for (size_t i = 0; i < ImTable::kSize && imt_equals; ++i) {
imt_equals = imt_equals && (super_imt->Get(i, image_pointer_size_) == imt_data[i]);
}
if (imt_equals) {
imt = super_imt;
}
}
}
if (imt == nullptr) {
LinearAlloc* allocator = GetAllocatorForClassLoader(klass->GetClassLoader());
imt = reinterpret_cast<ImTable*>(
allocator->Alloc(self, ImTable::SizeInBytes(image_pointer_size_)));
if (imt == nullptr) {
return false;
}
imt->Populate(imt_data, image_pointer_size_);
}
}
if (!klass->IsTemp() || (!init_done_ && klass->GetClassSize() == class_size)) {
// We don't need to retire this class as it has no embedded tables or it was created the
// correct size during class linker initialization.
CHECK_EQ(klass->GetClassSize(), class_size) << klass->PrettyDescriptor();
if (klass->ShouldHaveEmbeddedVTable()) {
klass->PopulateEmbeddedVTable(image_pointer_size_);
}
if (klass->ShouldHaveImt()) {
klass->SetImt(imt, image_pointer_size_);
}
// Update CHA info based on whether we override methods.
// Have to do this before setting the class as resolved which allows
// instantiation of klass.
if (cha_ != nullptr) {
cha_->UpdateAfterLoadingOf(klass);
}
// This will notify waiters on klass that saw the not yet resolved
// class in the class_table_ during EnsureResolved.
mirror::Class::SetStatus(klass, ClassStatus::kResolved, self);
h_new_class_out->Assign(klass.Get());
} else { // 如果目标类是可以实例化的
CHECK(!klass->IsResolved());
// Retire the temporary class and create the correctly sized resolved class.
StackHandleScope<1> hs(self);
// CopyOf 时将状态设置为 kResolving
auto h_new_class = hs.NewHandle(klass->CopyOf(self, class_size, imt, image_pointer_size_));
// Set arrays to null since we don't want to have multiple classes with the same ArtField or
// ArtMethod array pointers. If this occurs, it causes bugs in remembered sets since the GC
// may not see any references to the target space and clean the card for a class if another
// class had the same array pointer.
klass->SetMethodsPtrUnchecked(nullptr, 0, 0);
klass->SetSFieldsPtrUnchecked(nullptr);
klass->SetIFieldsPtrUnchecked(nullptr);
if (UNLIKELY(h_new_class == nullptr)) {
self->AssertPendingOOMException();
mirror::Class::SetStatus(klass, ClassStatus::kErrorUnresolved, self);
return false;
}
CHECK_EQ(h_new_class->GetClassSize(), class_size);
ObjectLock<mirror::Class> lock(self, h_new_class);
FixupTemporaryDeclaringClass(klass.Get(), h_new_class.Get());
{
WriterMutexLock mu(self, *Locks::classlinker_classes_lock_);
const ObjPtr<mirror::ClassLoader> class_loader = h_new_class.Get()->GetClassLoader();
ClassTable* const table = InsertClassTableForClassLoader(class_loader);
const ObjPtr<mirror::Class> existing =
table->UpdateClass(descriptor, h_new_class.Get(), ComputeModifiedUtf8Hash(descriptor));
if (class_loader != nullptr) {
// We updated the class in the class table, perform the write barrier so that the GC knows
// about the change.
WriteBarrier::ForEveryFieldWrite(class_loader);
}
CHECK_EQ(existing, klass.Get());
if (log_new_roots_) {
new_class_roots_.push_back(GcRoot<mirror::Class>(h_new_class.Get()));
}
}
// Update CHA info based on whether we override methods.
// Have to do this before setting the class as resolved which allows
// instantiation of klass.
if (cha_ != nullptr) {
cha_->UpdateAfterLoadingOf(h_new_class);
}
// This will notify waiters on temp class that saw the not yet resolved class in the
// class_table_ during EnsureResolved.
// 旧的class设置为kRetired
mirror::Class::SetStatus(klass, ClassStatus::kRetired, self);
CHECK_EQ(h_new_class->GetStatus(), ClassStatus::kResolving);
// This will notify waiters on new_class that saw the not yet resolved
// class in the class_table_ during EnsureResolved.
// 设置为解析完成状态
mirror::Class::SetStatus(h_new_class, ClassStatus::kResolved, self);
// Return the new class.
h_new_class_out->Assign(h_new_class.Get());
}
return true;
}kResolved - kVerifying - kVerified
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203verifier::FailureKind ClassLinker::VerifyClass(
Thread* self, Handle<mirror::Class> klass, verifier::HardFailLogMode log_level) {
{
// TODO: assert that the monitor on the Class is held
ObjectLock<mirror::Class> lock(self, klass);
// Is somebody verifying this now?
ClassStatus old_status = klass->GetStatus();
while (old_status == ClassStatus::kVerifying ||
old_status == ClassStatus::kVerifyingAtRuntime) {
lock.WaitIgnoringInterrupts();
// WaitIgnoringInterrupts can still receive an interrupt and return early, in this
// case we may see the same status again. b/62912904. This is why the check is
// greater or equal.
CHECK(klass->IsErroneous() || (klass->GetStatus() >= old_status))
<< "Class '" << klass->PrettyClass()
<< "' performed an illegal verification state transition from " << old_status
<< " to " << klass->GetStatus();
old_status = klass->GetStatus();
}
// The class might already be erroneous, for example at compile time if we attempted to verify
// this class as a parent to another.
if (klass->IsErroneous()) {
ThrowEarlierClassFailure(klass.Get());
return verifier::FailureKind::kHardFailure;
}
// Don't attempt to re-verify if already verified.
if (klass->IsVerified()) {
EnsureSkipAccessChecksMethods(klass, image_pointer_size_);
return verifier::FailureKind::kNoFailure;
}
// For AOT, don't attempt to re-verify if we have already found we should
// verify at runtime.
if (Runtime::Current()->IsAotCompiler() && klass->ShouldVerifyAtRuntime()) {
return verifier::FailureKind::kSoftFailure;
}
if (klass->GetStatus() == ClassStatus::kResolved) {
mirror::Class::SetStatus(klass, ClassStatus::kVerifying, self);
} else {
CHECK_EQ(klass->GetStatus(), ClassStatus::kRetryVerificationAtRuntime)
<< klass->PrettyClass();
CHECK(!Runtime::Current()->IsAotCompiler());
mirror::Class::SetStatus(klass, ClassStatus::kVerifyingAtRuntime, self);
}
// Skip verification if disabled.
if (!Runtime::Current()->IsVerificationEnabled()) {
mirror::Class::SetStatus(klass, ClassStatus::kVerified, self);
EnsureSkipAccessChecksMethods(klass, image_pointer_size_);
return verifier::FailureKind::kNoFailure;
}
}
VLOG(class_linker) << "Beginning verification for class: "
<< klass->PrettyDescriptor()
<< " in " << klass->GetDexCache()->GetLocation()->ToModifiedUtf8();
// Verify super class.
StackHandleScope<2> hs(self);
MutableHandle<mirror::Class> supertype(hs.NewHandle(klass->GetSuperClass()));
// If we have a superclass and we get a hard verification failure we can return immediately.
if (supertype != nullptr && !AttemptSupertypeVerification(self, klass, supertype)) {
CHECK(self->IsExceptionPending()) << "Verification error should be pending.";
return verifier::FailureKind::kHardFailure;
}
// Verify all default super-interfaces.
//
// (1) Don't bother if the superclass has already had a soft verification failure.
//
// (2) Interfaces shouldn't bother to do this recursive verification because they cannot cause
// recursive initialization by themselves. This is because when an interface is initialized
// directly it must not initialize its superinterfaces. We are allowed to verify regardless
// but choose not to for an optimization. If the interfaces is being verified due to a class
// initialization (which would need all the default interfaces to be verified) the class code
// will trigger the recursive verification anyway.
if ((supertype == nullptr || supertype->IsVerified()) // See (1)
&& !klass->IsInterface()) { // See (2)
int32_t iftable_count = klass->GetIfTableCount();
MutableHandle<mirror::Class> iface(hs.NewHandle<mirror::Class>(nullptr));
// Loop through all interfaces this class has defined. It doesn't matter the order.
for (int32_t i = 0; i < iftable_count; i++) {
iface.Assign(klass->GetIfTable()->GetInterface(i));
DCHECK(iface != nullptr);
// We only care if we have default interfaces and can skip if we are already verified...
if (LIKELY(!iface->HasDefaultMethods() || iface->IsVerified())) {
continue;
} else if (UNLIKELY(!AttemptSupertypeVerification(self, klass, iface))) {
// We had a hard failure while verifying this interface. Just return immediately.
CHECK(self->IsExceptionPending()) << "Verification error should be pending.";
return verifier::FailureKind::kHardFailure;
} else if (UNLIKELY(!iface->IsVerified())) {
// We softly failed to verify the iface. Stop checking and clean up.
// Put the iface into the supertype handle so we know what caused us to fail.
supertype.Assign(iface.Get());
break;
}
}
}
// At this point if verification failed, then supertype is the "first" supertype that failed
// verification (without a specific order). If verification succeeded, then supertype is either
// null or the original superclass of klass and is verified.
DCHECK(supertype == nullptr ||
supertype.Get() == klass->GetSuperClass() ||
!supertype->IsVerified());
// Try to use verification information from the oat file, otherwise do runtime verification.
const DexFile& dex_file = *klass->GetDexCache()->GetDexFile();
ClassStatus oat_file_class_status(ClassStatus::kNotReady);
bool preverified = VerifyClassUsingOatFile(dex_file, klass.Get(), oat_file_class_status);
VLOG(class_linker) << "Class preverified status for class "
<< klass->PrettyDescriptor()
<< " in " << klass->GetDexCache()->GetLocation()->ToModifiedUtf8()
<< ": "
<< preverified;
// If the oat file says the class had an error, re-run the verifier. That way we will get a
// precise error message. To ensure a rerun, test:
// mirror::Class::IsErroneous(oat_file_class_status) => !preverified
DCHECK(!mirror::Class::IsErroneous(oat_file_class_status) || !preverified);
std::string error_msg;
verifier::FailureKind verifier_failure = verifier::FailureKind::kNoFailure;
if (!preverified) {
verifier_failure = PerformClassVerification(self, klass, log_level, &error_msg);
}
// Verification is done, grab the lock again.
ObjectLock<mirror::Class> lock(self, klass);
if (preverified || verifier_failure != verifier::FailureKind::kHardFailure) {
if (!preverified && verifier_failure != verifier::FailureKind::kNoFailure) {
VLOG(class_linker) << "Soft verification failure in class "
<< klass->PrettyDescriptor()
<< " in " << klass->GetDexCache()->GetLocation()->ToModifiedUtf8()
<< " because: " << error_msg;
}
self->AssertNoPendingException();
// Make sure all classes referenced by catch blocks are resolved.
ResolveClassExceptionHandlerTypes(klass);
if (verifier_failure == verifier::FailureKind::kNoFailure) {
// Even though there were no verifier failures we need to respect whether the super-class and
// super-default-interfaces were verified or requiring runtime reverification.
if (supertype == nullptr || supertype->IsVerified()) {
mirror::Class::SetStatus(klass, ClassStatus::kVerified, self);
} else {
CHECK_EQ(supertype->GetStatus(), ClassStatus::kRetryVerificationAtRuntime);
mirror::Class::SetStatus(klass, ClassStatus::kRetryVerificationAtRuntime, self);
// Pretend a soft failure occurred so that we don't consider the class verified below.
verifier_failure = verifier::FailureKind::kSoftFailure;
}
} else {
CHECK_EQ(verifier_failure, verifier::FailureKind::kSoftFailure);
// Soft failures at compile time should be retried at runtime. Soft
// failures at runtime will be handled by slow paths in the generated
// code. Set status accordingly.
if (Runtime::Current()->IsAotCompiler()) {
mirror::Class::SetStatus(klass, ClassStatus::kRetryVerificationAtRuntime, self);
} else {
mirror::Class::SetStatus(klass, ClassStatus::kVerified, self);
// As this is a fake verified status, make sure the methods are _not_ marked
// kAccSkipAccessChecks later.
klass->SetVerificationAttempted();
}
}
} else {
VLOG(verifier) << "Verification failed on class " << klass->PrettyDescriptor()
<< " in " << klass->GetDexCache()->GetLocation()->ToModifiedUtf8()
<< " because: " << error_msg;
self->AssertNoPendingException();
ThrowVerifyError(klass.Get(), "%s", error_msg.c_str());
mirror::Class::SetStatus(klass, ClassStatus::kErrorResolved, self);
}
if (preverified || verifier_failure == verifier::FailureKind::kNoFailure) {
// Class is verified so we don't need to do any access check on its methods.
// Let the interpreter know it by setting the kAccSkipAccessChecks flag onto each
// method.
// Note: we're going here during compilation and at runtime. When we set the
// kAccSkipAccessChecks flag when compiling image classes, the flag is recorded
// in the image and is set when loading the image.
if (UNLIKELY(Runtime::Current()->IsVerificationSoftFail())) {
// Never skip access checks if the verification soft fail is forced.
// Mark the class as having a verification attempt to avoid re-running the verifier.
klass->SetVerificationAttempted();
} else {
EnsureSkipAccessChecksMethods(klass, image_pointer_size_);
}
}
// Done verifying. Notify the compiler about the verification status, in case the class
// was verified implicitly (eg super class of a compiled class).
if (Runtime::Current()->IsAotCompiler()) {
Runtime::Current()->GetCompilerCallbacks()->UpdateClassState(
ClassReference(&klass->GetDexFile(), klass->GetDexClassDefIndex()), klass->GetStatus());
}
return verifier_failure;
}kVerified - kInitializing - kInitialized
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294bool ClassLinker::InitializeClass(Thread* self, Handle<mirror::Class> klass,
bool can_init_statics, bool can_init_parents) {
// see JLS 3rd edition, 12.4.2 "Detailed Initialization Procedure" for the locking protocol
// Are we already initialized and therefore done?
// Note: we differ from the JLS here as we don't do this under the lock, this is benign as
// an initialized class will never change its state.
if (klass->IsInitialized()) {
return true;
}
// Fast fail if initialization requires a full runtime. Not part of the JLS.
if (!CanWeInitializeClass(klass.Get(), can_init_statics, can_init_parents)) {
return false;
}
self->AllowThreadSuspension();
uint64_t t0;
{
ObjectLock<mirror::Class> lock(self, klass);
// Re-check under the lock in case another thread initialized ahead of us.
if (klass->IsInitialized()) {
return true;
}
// Was the class already found to be erroneous? Done under the lock to match the JLS.
if (klass->IsErroneous()) {
ThrowEarlierClassFailure(klass.Get(), true, /* log= */ true);
VlogClassInitializationFailure(klass);
return false;
}
CHECK(klass->IsResolved() && !klass->IsErroneousResolved())
<< klass->PrettyClass() << ": state=" << klass->GetStatus();
if (!klass->IsVerified()) {
VerifyClass(self, klass);
if (!klass->IsVerified()) {
// We failed to verify, expect either the klass to be erroneous or verification failed at
// compile time.
if (klass->IsErroneous()) {
// The class is erroneous. This may be a verifier error, or another thread attempted
// verification and/or initialization and failed. We can distinguish those cases by
// whether an exception is already pending.
if (self->IsExceptionPending()) {
// Check that it's a VerifyError.
DCHECK_EQ("java.lang.Class<java.lang.VerifyError>",
mirror::Class::PrettyClass(self->GetException()->GetClass()));
} else {
// Check that another thread attempted initialization.
DCHECK_NE(0, klass->GetClinitThreadId());
DCHECK_NE(self->GetTid(), klass->GetClinitThreadId());
// Need to rethrow the previous failure now.
ThrowEarlierClassFailure(klass.Get(), true);
}
VlogClassInitializationFailure(klass);
} else {
CHECK(Runtime::Current()->IsAotCompiler());
CHECK_EQ(klass->GetStatus(), ClassStatus::kRetryVerificationAtRuntime);
self->AssertNoPendingException();
self->SetException(Runtime::Current()->GetPreAllocatedNoClassDefFoundError());
}
self->AssertPendingException();
return false;
} else {
self->AssertNoPendingException();
}
// A separate thread could have moved us all the way to initialized. A "simple" example
// involves a subclass of the current class being initialized at the same time (which
// will implicitly initialize the superclass, if scheduled that way). b/28254258
DCHECK(!klass->IsErroneous()) << klass->GetStatus();
if (klass->IsInitialized()) {
return true;
}
}
// If the class is ClassStatus::kInitializing, either this thread is
// initializing higher up the stack or another thread has beat us
// to initializing and we need to wait. Either way, this
// invocation of InitializeClass will not be responsible for
// running <clinit> and will return.
if (klass->GetStatus() == ClassStatus::kInitializing) {
// Could have got an exception during verification.
if (self->IsExceptionPending()) {
VlogClassInitializationFailure(klass);
return false;
}
// We caught somebody else in the act; was it us?
if (klass->GetClinitThreadId() == self->GetTid()) {
// Yes. That's fine. Return so we can continue initializing.
return true;
}
// No. That's fine. Wait for another thread to finish initializing.
return WaitForInitializeClass(klass, self, lock);
}
// Try to get the oat class's status for this class if the oat file is present. The compiler
// tries to validate superclass descriptors, and writes the result into the oat file.
// Runtime correctness is guaranteed by classpath checks done on loading. If the classpath
// is different at runtime than it was at compile time, the oat file is rejected. So if the
// oat file is present, the classpaths must match, and the runtime time check can be skipped.
bool has_oat_class = false;
const Runtime* runtime = Runtime::Current();
const OatFile::OatClass oat_class = (runtime->IsStarted() && !runtime->IsAotCompiler())
? OatFile::FindOatClass(klass->GetDexFile(), klass->GetDexClassDefIndex(), &has_oat_class)
: OatFile::OatClass::Invalid();
if (oat_class.GetStatus() < ClassStatus::kSuperclassValidated &&
!ValidateSuperClassDescriptors(klass)) {
mirror::Class::SetStatus(klass, ClassStatus::kErrorResolved, self);
return false;
}
self->AllowThreadSuspension();
CHECK_EQ(klass->GetStatus(), ClassStatus::kVerified) << klass->PrettyClass()
<< " self.tid=" << self->GetTid() << " clinit.tid=" << klass->GetClinitThreadId();
// From here out other threads may observe that we're initializing and so changes of state
// require the a notification.
klass->SetClinitThreadId(self->GetTid());
// 初始化中
mirror::Class::SetStatus(klass, ClassStatus::kInitializing, self);
t0 = NanoTime();
}
// Initialize super classes, must be done while initializing for the JLS.
if (!klass->IsInterface() && klass->HasSuperClass()) {
ObjPtr<mirror::Class> super_class = klass->GetSuperClass();
if (!super_class->IsInitialized()) {
CHECK(!super_class->IsInterface());
CHECK(can_init_parents);
StackHandleScope<1> hs(self);
Handle<mirror::Class> handle_scope_super(hs.NewHandle(super_class));
bool super_initialized = InitializeClass(self, handle_scope_super, can_init_statics, true);
if (!super_initialized) {
// The super class was verified ahead of entering initializing, we should only be here if
// the super class became erroneous due to initialization.
// For the case of aot compiler, the super class might also be initializing but we don't
// want to process circular dependencies in pre-compile.
CHECK(self->IsExceptionPending())
<< "Super class initialization failed for "
<< handle_scope_super->PrettyDescriptor()
<< " that has unexpected status " << handle_scope_super->GetStatus()
<< "\nPending exception:\n"
<< (self->GetException() != nullptr ? self->GetException()->Dump() : "");
ObjectLock<mirror::Class> lock(self, klass);
// Initialization failed because the super-class is erroneous.
mirror::Class::SetStatus(klass, ClassStatus::kErrorResolved, self);
return false;
}
}
}
if (!klass->IsInterface()) {
// Initialize interfaces with default methods for the JLS.
size_t num_direct_interfaces = klass->NumDirectInterfaces();
// Only setup the (expensive) handle scope if we actually need to.
if (UNLIKELY(num_direct_interfaces > 0)) {
StackHandleScope<1> hs_iface(self);
MutableHandle<mirror::Class> handle_scope_iface(hs_iface.NewHandle<mirror::Class>(nullptr));
for (size_t i = 0; i < num_direct_interfaces; i++) {
handle_scope_iface.Assign(mirror::Class::GetDirectInterface(self, klass.Get(), i));
CHECK(handle_scope_iface != nullptr) << klass->PrettyDescriptor() << " iface #" << i;
CHECK(handle_scope_iface->IsInterface());
if (handle_scope_iface->HasBeenRecursivelyInitialized()) {
// We have already done this for this interface. Skip it.
continue;
}
// We cannot just call initialize class directly because we need to ensure that ALL
// interfaces with default methods are initialized. Non-default interface initialization
// will not affect other non-default super-interfaces.
bool iface_initialized = InitializeDefaultInterfaceRecursive(self,
handle_scope_iface,
can_init_statics,
can_init_parents);
if (!iface_initialized) {
ObjectLock<mirror::Class> lock(self, klass);
// Initialization failed because one of our interfaces with default methods is erroneous.
mirror::Class::SetStatus(klass, ClassStatus::kErrorResolved, self);
return false;
}
}
}
}
const size_t num_static_fields = klass->NumStaticFields();
if (num_static_fields > 0) {
const dex::ClassDef* dex_class_def = klass->GetClassDef();
CHECK(dex_class_def != nullptr);
StackHandleScope<3> hs(self);
Handle<mirror::ClassLoader> class_loader(hs.NewHandle(klass->GetClassLoader()));
Handle<mirror::DexCache> dex_cache(hs.NewHandle(klass->GetDexCache()));
// Eagerly fill in static fields so that the we don't have to do as many expensive
// Class::FindStaticField in ResolveField.
for (size_t i = 0; i < num_static_fields; ++i) {
ArtField* field = klass->GetStaticField(i);
const uint32_t field_idx = field->GetDexFieldIndex();
ArtField* resolved_field = dex_cache->GetResolvedField(field_idx, image_pointer_size_);
if (resolved_field == nullptr) {
// Populating cache of a dex file which defines `klass` should always be allowed.
DCHECK(!hiddenapi::ShouldDenyAccessToMember(
field,
hiddenapi::AccessContext(class_loader.Get(), dex_cache.Get()),
hiddenapi::AccessMethod::kNone));
dex_cache->SetResolvedField(field_idx, field, image_pointer_size_);
} else {
DCHECK_EQ(field, resolved_field);
}
}
annotations::RuntimeEncodedStaticFieldValueIterator value_it(dex_cache,
class_loader,
this,
*dex_class_def);
const DexFile& dex_file = *dex_cache->GetDexFile();
if (value_it.HasNext()) {
ClassAccessor accessor(dex_file, *dex_class_def);
CHECK(can_init_statics);
for (const ClassAccessor::Field& field : accessor.GetStaticFields()) {
if (!value_it.HasNext()) {
break;
}
ArtField* art_field = ResolveField(field.GetIndex(),
dex_cache,
class_loader,
/* is_static= */ true);
if (Runtime::Current()->IsActiveTransaction()) {
value_it.ReadValueToField<true>(art_field);
} else {
value_it.ReadValueToField<false>(art_field);
}
if (self->IsExceptionPending()) {
break;
}
value_it.Next();
}
DCHECK(self->IsExceptionPending() || !value_it.HasNext());
}
}
if (!self->IsExceptionPending()) {
ArtMethod* clinit = klass->FindClassInitializer(image_pointer_size_);
if (clinit != nullptr) {
CHECK(can_init_statics);
JValue result;
clinit->Invoke(self, nullptr, 0, &result, "V");
}
}
self->AllowThreadSuspension();
uint64_t t1 = NanoTime();
bool success = true;
{
ObjectLock<mirror::Class> lock(self, klass);
if (self->IsExceptionPending()) {
WrapExceptionInInitializer(klass);
mirror::Class::SetStatus(klass, ClassStatus::kErrorResolved, self);
success = false;
} else if (Runtime::Current()->IsTransactionAborted()) {
// The exception thrown when the transaction aborted has been caught and cleared
// so we need to throw it again now.
VLOG(compiler) << "Return from class initializer of "
<< mirror::Class::PrettyDescriptor(klass.Get())
<< " without exception while transaction was aborted: re-throw it now.";
Runtime::Current()->ThrowTransactionAbortError(self);
mirror::Class::SetStatus(klass, ClassStatus::kErrorResolved, self);
success = false;
} else {
RuntimeStats* global_stats = Runtime::Current()->GetStats();
RuntimeStats* thread_stats = self->GetStats();
++global_stats->class_init_count;
++thread_stats->class_init_count;
global_stats->class_init_time_ns += (t1 - t0);
thread_stats->class_init_time_ns += (t1 - t0);
// Set the class as initialized except if failed to initialize static fields.
// 初始化完成
mirror::Class::SetStatus(klass, ClassStatus::kInitialized, self);
if (VLOG_IS_ON(class_linker)) {
std::string temp;
LOG(INFO) << "Initialized class " << klass->GetDescriptor(&temp) << " from " <<
klass->GetLocation();
}
// Opportunistically set static method trampolines to their destination.
FixupStaticTrampolines(klass.Get());
}
}
return success;
}