应用启动时,tinker的verifyclass

来源:互联网 发布:两少一宽废除知乎 编辑:程序博客网 时间:2024/06/06 09:31

如果自己的项目使用了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__);273274  // 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);175176  // 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  }183184  const uint8_t* class_data = dex_file->GetClassData(*class_def);185  if (class_data == nullptr) {186    // empty class, probably a marker interface187    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 a3937  // precise error message. To ensure a rerun, test:3938  //     oat_file_class_status == mirror::Class::kStatusError => !preverified3939  DCHECK(!(oat_file_class_status == mirror::Class::kStatusError) || !preverified);39403941  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了。


原创粉丝点击