应用启动时,tinker的verifyclass

如果自己的项目使用了tinker热补丁,那么,会发现,启动应用时的systrace图如下,会多出一坨的verifyclass片段,导致时间慢了很多。




这段verifyclass的代码如下

http://androidxref.com/7.1.1_r6/xref/art/runtime/verifier/method_verifier.cc#262

262MethodVerifier::FailureKind MethodVerifier::VerifyClass(Thread* self,
263                                                        const DexFile* dex_file,
264                                                        Handle<mirror::DexCache> dex_cache,
265                                                        Handle<mirror::ClassLoader> class_loader,
266                                                        const DexFile::ClassDef* class_def,
267                                                        CompilerCallbacks* callbacks,
268                                                        bool allow_soft_failures,
269                                                        LogSeverity log_level,
270                                                        std::string* error) {
271  DCHECK(class_def != nullptr);
272  ScopedTrace trace(__FUNCTION__);
273
274  // A class must not be abstract and final.
275  if ((class_def->access_flags_ & (kAccAbstract | kAccFinal)) == (kAccAbstract | kAccFinal)) {
276    *error = "Verifier rejected class ";
277    *error += PrettyDescriptor(dex_file->GetClassDescriptor(*class_def));
278    *error += ": class is abstract and final.";
279    return kHardFailure;
280  }
281


android 6.0也有这段代码,但是没有输出systrace

167MethodVerifier::FailureKind MethodVerifier::VerifyClass(Thread* self,
168                                                        const DexFile* dex_file,
169                                                        Handle<mirror::DexCache> dex_cache,
170                                                        Handle<mirror::ClassLoader> class_loader,
171                                                        const DexFile::ClassDef* class_def,
172                                                        bool allow_soft_failures,
173                                                        std::string* error) {
174  DCHECK(class_def != nullptr);
175
176  // A class must not be abstract and final.
177  if ((class_def->access_flags_ & (kAccAbstract | kAccFinal)) == (kAccAbstract | kAccFinal)) {
178    *error = "Verifier rejected class ";
179    *error += PrettyDescriptor(dex_file->GetClassDescriptor(*class_def));
180    *error += ": class is abstract and final.";
181    return kHardFailure;
182  }
183
184  const uint8_t* class_data = dex_file->GetClassData(*class_def);
185  if (class_data == nullptr) {
186    // empty class, probably a marker interface
187    return kNoFailure;
188  }


而且正常的base.apk是不会出现verifyclass的,原因是这里

http://androidxref.com/7.1.1_r6/xref/art/runtime/class_linker.cc#3945

3935  bool preverified = VerifyClassUsingOatFile(dex_file, klass.Get(), oat_file_class_status);
3936  // If the oat file says the class had an error, re-run the verifier. That way we will get a
3937  // precise error message. To ensure a rerun, test:
3938  //     oat_file_class_status == mirror::Class::kStatusError => !preverified
3939  DCHECK(!(oat_file_class_status == mirror::Class::kStatusError) || !preverified);
3940
3941  verifier::MethodVerifier::FailureKind verifier_failure = verifier::MethodVerifier::kNoFailure;
3942  std::string error_msg;
3943  if (!preverified) {
3944    Runtime* runtime = Runtime::Current();
3945    verifier_failure = verifier::MethodVerifier::VerifyClass(self,
3946                                                             klass.Get(),
3947                                                             runtime->GetCompilerCallbacks(),
3948                                                             runtime->IsAotCompiler(),
3949                                                             log_level,
3950                                                             &error_msg);
3951  }
3952


这里,这里的条件是,

VerifyClassUsingOatFile

返回false才需要verifyclass,在010editor里,就是oat_class内的status的值,当这个值为10或者8时,就是dex2oat时已经verifyclass,并且把这个状态保存到了oat文件内。




当status<=6时,表示该class是没有verify的,需要在启动时verifyclass

base.apk在dex2oat时,就已经完成verifyclass,只有tinker的补丁classes2.dex classes3.dex在dex2oat时不能正常verifyclass,所以,启动时才需要verifyclass。


tinker在dex2oat时不能正常verifyclass的原因,是因为他是一个个dex文件进行dex2oat的,如果把它压缩成一整个apk,再进行dex2oat的话,就能完整verifyclass了。

此外,淘宝的插件化也存在这个问题,但是淘宝自己把自己的verify_标识置为0了。


猜你喜欢

转载自blog.csdn.net/jwhwzzh/article/details/76930480