美文网首页
PathClassLoader加载与查找类

PathClassLoader加载与查找类

作者: None_Ling | 来源:发表于2020-09-10 17:14 被阅读0次

    简述

    PathClassLoader加载的过程 :

    • 通过DexPathList.addDexPath来加载Dex文件
    • 通过makeDexElements来加载DexElement , 每一个Element就是一个Dex
    • 在Native层 , 加载Oat/dex文件
    • 根据加载到内存的基址来找到各个Section
    • 进行DexFile文件的校验
    • 校验成功后 , 通过ClassLinker->class_table添加class_table
    • 最后返回dex_files数组所在的Cookie

    PathClassLoader的查找过程 :

    • 通过DexFile.loadClassBinaryName加载
    • 调用到dalvik_system_DexFile.cc中的DexFile_defineClassNative函数
    • Cookie也就是dex_files基址传给Native , 初始化oat_file以及dex_files
    • 根据类名生成描述符descriptor
    • 遍历dex_files , 从dex_file中查找Class

    PathClassLoader

    PathClassLoader继承自BaseDexClassLoader , 主要是把dexPath传递给BaseDexClassLoader

    public class PathClassLoader extends BaseDexClassLoader {
    
        public PathClassLoader(String dexPath, ClassLoader parent) {
            super(dexPath, null, null, parent);
        }
        public PathClassLoader(String dexPath, String librarySearchPath, ClassLoader parent) {
            super(dexPath, null, librarySearchPath, parent);
        }
    }
    

    BaseDexClassLoader

    主要是通过DexPathList来查找类 , 以及添加Dex路径 , 初始化DexFile的

    public class BaseDexClassLoader extends ClassLoader {
    
        public BaseDexClassLoader(String dexPath, File optimizedDirectory,
                String librarySearchPath, ClassLoader parent) {
            super(parent);
            this.pathList = new DexPathList(this, dexPath, librarySearchPath, null);
        }
    
        @Override
        protected Class<?> findClass(String name) throws ClassNotFoundException {
            List<Throwable> suppressedExceptions = new ArrayList<Throwable>();
            Class c = pathList.findClass(name, suppressedExceptions);
            if (c == null) {
                ClassNotFoundException cnfe = new ClassNotFoundException(
                        "Didn't find class \"" + name + "\" on path: " + pathList);
                for (Throwable t : suppressedExceptions) {
                    cnfe.addSuppressed(t);
                }
                throw cnfe;
            }
            return c;
        }
    
        public void addDexPath(String dexPath) {
            pathList.addDexPath(dexPath, null /*optimizedDirectory*/);
        }
    }
    

    DexPathList

    1. DexPathList构造函数
    • 通过makeDexElements加载Dex文件 , 生成Element对象
    • 通过makePathElement加载动态链接库 , 生成Element对象
    public DexPathList(ClassLoader definingContext, String dexPath,
                String librarySearchPath, File optimizedDirectory) {  
            ...
            // 通过makeDexElements来加载dexPath的路径
            this.dexElements = makeDexElements(splitDexPath(dexPath), optimizedDirectory,
                                               suppressedExceptions, definingContext);
    
            // 初始化so的路径
            this.nativeLibraryDirectories = splitPaths(librarySearchPath, false);
            // 初始化系统So路径
            this.systemNativeLibraryDirectories =
                    splitPaths(System.getProperty("java.library.path"), true);
            List<File> allNativeLibraryDirectories = new ArrayList<>(nativeLibraryDirectories);
            // 添加所有So路径集合
            allNativeLibraryDirectories.addAll(systemNativeLibraryDirectories);
            // 加载动态链接库的Element
            this.nativeLibraryPathElements = makePathElements(allNativeLibraryDirectories);
            ...
        }
    
    1. makeDexElements
    • 遍历Dex文件 , 加载Dex文件 , 放入Elements数组中
    private static Element[] makeDexElements(List<File> files, File optimizedDirectory,
                List<IOException> suppressedExceptions, ClassLoader loader) {
          Element[] elements = new Element[files.size()];
          int elementsPos = 0;
          // 遍历所有的Dex文件路径
          for (File file : files) {
              if (file.isDirectory()) {
                  // 将目录文件放到对应的数组中
                  elements[elementsPos++] = new Element(file);
              } else if (file.isFile()) {
                  String name = file.getName();
                  // 判断是否以.dex结尾
                  if (name.endsWith(DEX_SUFFIX)) {
                      try {
                          // 通过loadDexFile加载dexs文件
                          DexFile dex = loadDexFile(file, optimizedDirectory, loader, elements);
                          if (dex != null) {
                              // 将dex放到Elements数组中
                              elements[elementsPos++] = new Element(dex, null);
                          }
                      } catch (IOException suppressed) {
                      }
                  } else {
                      DexFile dex = null;
                      try {
                          // 如果不以dex结尾也会通过`loadDexFile`尝试加载
                          dex = loadDexFile(file, optimizedDirectory, loader, elements);
                      } catch (IOException suppressed) {
                          suppressedExceptions.add(suppressed);
                      }
                      if (dex == null) {
                          // 如果加载失败 , 将文件放到elements中
                          elements[elementsPos++] = new Element(file);
                      } else {
                          elements[elementsPos++] = new Element(dex, file);
                      }
                  }
              } else {
                  System.logW("ClassLoader referenced unknown path: " + file);
              }
          }
          return elements;
        }
    
    1. loadDexFile
    • 通过两种方式加载DexFile
    private static DexFile loadDexFile(File file, File optimizedDirectory, ClassLoader loader,
                                           Element[] elements)
                throws IOException {
            if (optimizedDirectory == null) {
                // 如果odex文件路径为空的话 , 则会直接创建DexFile
                return new DexFile(file, loader, elements);
            } else {
                // 如果odex文件路径不为空的话 , 则会通过DexFile.loadDex从odex中直接读取
                String optimizedPath = optimizedPathFor(file, optimizedDirectory);
                return DexFile.loadDex(file.getPath(), optimizedPath, 0, loader, elements);
            }
        }
    
    1. DexFile
    • 校验uid
    • 通过openDexFileNative加载Dex文件
    • 返回Cookie代表JNI层dex_file的指针
    private DexFile(String sourceName, String outputName, int flags, ClassLoader loader,
                DexPathList.Element[] elements) throws IOException {
            if (outputName != null) {
                try {
                    String parent = new File(outputName).getParent();
                    // 检查文件uid是否相同 , 如果不同的话 , 则抛异常
                    if (Libcore.os.getuid() != Libcore.os.stat(parent).st_uid) {
                        throw new IllegalArgumentException("Optimized data directory " + parent
                                + " is not owned by the current user. Shared storage cannot protect"
                                + " your application from code injection attacks.");
                    }
                } catch (ErrnoException ignored) {
                    // assume we'll fail with a more contextual error later
                }
            }
            // 调用openDexFileNative函数 , 加载Dex文件
            mCookie = openDexFile(sourceName, outputName, flags, loader, elements);
            mInternalCookie = mCookie;
            mFileName = sourceName;
            //System.out.println("DEX FILE cookie is " + mCookie + " sourceName=" + sourceName + " outputName=" + outputName);
        }
    
    1. openDexFileNative
    • 获取ClassLinker对象
    • 通过OatFilemanager.OpenDexFilesFromOat从oat文件中生成dex的数组(Vector)
    • 将·dex_files·数组的地址返回给Java层
    static jobject DexFile_openDexFileNative(JNIEnv* env,
                                             jclass,
                                             jstring javaSourceName,
                                             jstring javaOutputName ATTRIBUTE_UNUSED,
                                             jint flags ATTRIBUTE_UNUSED,
                                             jobject class_loader,
                                             jobjectArray dex_elements) {
      // 获取Runtime
      Runtime* const runtime = Runtime::Current();
      // 获取ClassLinker
      ClassLinker* linker = runtime->GetClassLinker();
      std::vector<std::unique_ptr<const DexFile>> dex_files;
      std::vector<std::string> error_msgs;
      const OatFile* oat_file = nullptr;
      // 通过OpenDexFilesFromOat函数加载文件
      dex_files = runtime->GetOatFileManager().OpenDexFilesFromOat(sourceName.c_str(),
                                                                   class_loader,
                                                                   dex_elements,
                                                                   /*out*/ &oat_file,
                                                                   /*out*/ &error_msgs);
      // 如果dex_files不为空的话
      if (!dex_files.empty()) {
        // 将DexFile转成地址数组
        jlongArray array = ConvertDexFilesToJavaArray(env, oat_file, dex_files);
        if (array == nullptr) {
          ScopedObjectAccess soa(env);
          // 如果array为空 , 则释放defFile
          for (auto& dex_file : dex_files) {
            if (linker->IsDexFileRegistered(soa.Self(), *dex_file)) {
              dex_file.release();
            }
          }
        }
        // 返回array数组作为Cookie返回
        return array;
      } else {
        ScopedObjectAccess soa(env);
        CHECK(!error_msgs.empty());
       // 抛异常
        auto it = error_msgs.begin();
        auto itEnd = error_msgs.end();
        for ( ; it != itEnd; ++it) {
          ThrowWrappedIOException("%s", it->c_str());
        }
        return nullptr;
      }
    }
    
    1. art/runtime/oat_file_manager.cc
    • 初始化oat_file_assistant对象 , 主要用于保存odex、oat路径
    • oat_file类型为ElfOatFile
    • 通过oat_file_assistant.OpenImageSpace初始化ImageSpace, 其中会读取oat文件的header、data , 然后校验oat文件的checksum
    • 接着校验SectionMap , 最后得到ImageSpace
    • 将ImageSpace添加到Heap
    • 主要通过ClassLinker->AddImageSpace将oat/dex文件添加到JNIEnv中
    • 添加成功后 , 释放imageSpace
    • 如果没有添加成功 , 则通过LoadDexFiles重新尝试加载一次
    td::vector<std::unique_ptr<const DexFile>> OatFileManager::OpenDexFilesFromOat(
        const char* dex_location,
        jobject class_loader,
        jobjectArray dex_elements,
        const OatFile** out_oat_file,
        std::vector<std::string>* error_msgs) {
      // 此处不用Mutex进行并发 , 因为分配oat/dex文件会导致大量GC
      Thread* const self = Thread::Current();
      // 验证没有锁
      Locks::mutator_lock_->AssertNotHeld(self);
      // 获取Rumtine
      Runtime* const runtime = Runtime::Current();
      // 创建OatFileAssistant对象 , 内部会判断当前的指令集与SOC架构是否匹配
      // 同时会找到odex以及oat文件的路径
      OatFileAssistant oat_file_assistant(dex_location,
                                          kRuntimeISA,
                                          !runtime->IsAotCompiler());
      ... 
      const OatFile* source_oat_file = nullptr;
      // 从路径中读取oat_file , 类型为ElfOatFile
      std::unique_ptr<const OatFile> oat_file(oat_file_assistant.GetBestOatFile().release());
     
        if (accept_oat_file) {
          VLOG(class_linker) << "Registering " << oat_file->GetLocation();
          // 将oat_file插入oat_files_队列中
          source_oat_file = RegisterOatFile(std::move(oat_file));
          *out_oat_file = source_oat_file;
        }
      }
      // 声明oat文件中的dex_file
      std::vector<std::unique_ptr<const DexFile>> dex_files;
    
      // 开始从oat文件中加载dex
      if (source_oat_file != nullptr) {
        bool added_image_space = false;
        // 判断是否为可执行文件 , 因为是ELF文件 , 所以为true
        if (source_oat_file->IsExecutable()) {
          // 调用oat_file_assistant.OpenImageSpace函数将oat文件加载到内存中
          // 并且初始化class_,method_等数组对象
          std::unique_ptr<gc::space::ImageSpace> image_space =
              kEnableAppImage ? oat_file_assistant.OpenImageSpace(source_oat_file) : nullptr;
          // 如果加载成功
          if (image_space != nullptr) {
              {
                ...
                // 将oat等镜像空间添加到Heap中
                runtime->GetHeap()->AddSpace(image_space.get());
              }
              {
                // 将dex_files添加到ClassLinker中
                added_image_space = runtime->GetClassLinker()->AddImageSpace(image_space.get(),h_loader,dex_elements, dex_location,
                                                                             /*out*/&dex_files,
                                                                             /*out*/&temp_error_msg);
              }
              // 如果添加成功 , 则释放image_space
              if (added_image_space) {
                image_space.release();
              } else {
                LOG(INFO) << "Failed to add image file " << temp_error_msg;
                // 否则清理dex_files
                dex_files.clear();
                {
                  // 清理Space
                  runtime->GetHeap()->RemoveSpace(image_space.get());
                }
              }
            }
          }
        }
        if (!added_image_space) {
          DCHECK(dex_files.empty());
          // 如果classLinker添加失败 , 则重新加载一次
          dex_files = oat_file_assistant.LoadDexFiles(*source_oat_file, dex_location);
        }
         ...
      return dex_files;
    }
    
    1. ClassLinker. AddImageSpace
    • ImageSpace中获取OatFile指针
    • 遍历dex_caches, 通过OpenOatDexFile生成dex_file对象
    • dex_file添加到out_dex_files数组中 , 在函数结束后返回
    • 校验ClassLoader与BootClassLoader
    • dex_file_name加入loader_dex_file_names
    • classLoaderClassTable添加到Class
    bool ClassLinker::AddImageSpace(
        gc::space::ImageSpace* space,
        Handle<mirror::ClassLoader> class_loader,
        jobjectArray dex_elements,
        const char* dex_location,
        std::vector<std::unique_ptr<const DexFile>>* out_dex_files,
        std::string* error_msg) {
      // 初始化参数
      Runtime* const runtime = Runtime::Current();
      gc::Heap* const heap = runtime->GetHeap();
      Thread* const self = Thread::Current();
      ...
      // 从header中获取dex_Cache_object引用
      Handle<mirror::ObjectArray<mirror::DexCache>> dex_caches(
          hs.NewHandle(dex_caches_object->AsObjectArray<mirror::DexCache>()));
      // 从header中获取Class数组的日志
      Handle<mirror::ObjectArray<mirror::Class>> class_roots(hs.NewHandle(
          header.GetImageRoot(ImageHeader::kClassRoots)->AsObjectArray<mirror::Class>()));
      // 初始化 ClassLoader
      MutableHandle<mirror::ClassLoader> image_class_loader(hs.NewHandle(
          app_image ? header.GetImageRoot(ImageHeader::kClassLoader)->AsClassLoader() : nullptr));
      // 从ImageSpace获取OatFile
      const OatFile* oat_file = space->GetOatFile();
       ... 
      // 开始遍历dex_caches
      for (int32_t i = 0; i < dex_caches->GetLength(); i++) {
        // 获取DexCache指针
        ObjPtr<mirror::DexCache> dex_cache = dex_caches->Get(i);
        // 获取dex_cache的路径
        std::string dex_file_location(dex_cache->GetLocation()->ToModifiedUtf8());
        // 通过OpenOatFile打开Oat文件 , 获取DexFile
        std::unique_ptr<const DexFile> dex_file = OpenOatDexFile(oat_file,
                                                                 dex_file_location.c_str(),
                                                                 error_msg);
    
          ...
          //  设置dex_cache对象
          dex_cache->SetDexFile(dex_file.get());
         //  将dex_file加到out_dex_files数组中 , 后面返回
          out_dex_files->push_back(std::move(dex_file));
       }
       ...
      // 如果是oat文件话
      if (app_image) {
        ScopedObjectAccessUnchecked soa(Thread::Current());
        // 接下来要开始校验
        // 判断当前ClassLoader是否是BootClassLoader
        if (IsBootClassLoader(soa, image_class_loader.Get())) {
          *error_msg = "Unexpected BootClassLoader in app image";
          return false;
        }
        std::list<ObjPtr<mirror::String>> image_dex_file_names;
        std::string temp_error_msg;
        if (!FlattenPathClassLoader(image_class_loader.Get(), &image_dex_file_names, &temp_error_msg)) {
          *error_msg = StringPrintf("Failed to flatten image class loader hierarchy '%s'",
                                    temp_error_msg.c_str());
          return false;
        }
        std::list<ObjPtr<mirror::String>> loader_dex_file_names;
        if (!FlattenPathClassLoader(class_loader.Get(), &loader_dex_file_names, &temp_error_msg)) {
          *error_msg = StringPrintf("Failed to flatten class loader hierarchy '%s'",
                                    temp_error_msg.c_str());
          return false;
        }
        // 遍历elements , 将有效的dex添加到已加载到dexfile中
        auto elements = soa.Decode<mirror::ObjectArray<mirror::Object>>(dex_elements);
        for (size_t i = 0, num_elems = elements->GetLength(); i < num_elems; ++i) {
          ObjPtr<mirror::Object> element = elements->GetWithoutChecks(i);
          if (element != nullptr) {
            // If we are somewhere in the middle of the array, there may be nulls at the end.
            ObjPtr<mirror::String> name;
            // 在element中检查其中的dexfile以及name是否为空
            //  不为空则将dex的名称push到loader_dex_file_names中
            if (GetDexPathListElementName(element, &name) && name != nullptr) {
              loader_dex_file_names.push_back(name);
            }
          }
        }
      ...
       //  开始更新ClassLinker中的class_table
      ClassTable* class_table = nullptr;
      {
        WriterMutexLock mu(self, *Locks::classlinker_classes_lock_);
        // 创建ClassLoader中的ClassTable
        class_table = InsertClassTableForClassLoader(class_loader.Get());
      }
       // 创建临时的ClassTable
      ClassTable::ClassSet temp_set;
       // 从oat文件中读取ClassTable的Section
      const ImageSection& class_table_section = header.GetImageSection(ImageHeader::kSectionClassTable);
        // 判断classTable的Section大小是否大于0
      const bool added_class_table = class_table_section.Size() > 0;
      if (added_class_table) {
        const uint64_t start_time2 = NanoTime();
        size_t read_count = 0;
        // 如果存在ClassTableSection的话 , 则读取出来保存到temp_set中
        temp_set = ClassTable::ClassSet(space->Begin() + class_table_section.Offset(),
                                        /*make copy*/false,
                                        &read_count);
        VLOG(image) << "Adding class table classes took " << PrettyDuration(NanoTime() - start_time2);
      }
      if (app_image) {
        bool forward_dex_cache_arrays = false;
        // 校验ClassLoader以及DexCache
        if (!UpdateAppImageClassLoadersAndDexCaches(space,
                                                    class_loader,
                                                    dex_caches,
                                                    &temp_set,
                                                    /*out*/&forward_dex_cache_arrays,
                                                    /*out*/error_msg)) {
          return false;
        }
      ...
      // 把oat文件插入到class_table中
      if (!oat_file->GetBssGcRoots().empty()) {
        // Insert oat file to class table for visiting .bss GC roots.
        class_table->InsertOatFile(oat_file);
      }
      if (added_class_table) {
        // 如果需要添加到classtable , 则添加到class_table中
        WriterMutexLock mu(self, *Locks::classlinker_classes_lock_);
        class_table->AddClassSet(std::move(temp_set));
      }
      ...
      return true;
    }
    
    
    1. OpenOatDexFile
    static std::unique_ptr<const DexFile> OpenOatDexFile(const OatFile* oat_file,
                                                         const char* location,
                                                         std::string* error_msg)
        REQUIRES_SHARED(Locks::mutator_lock_) {
      DCHECK(error_msg != nullptr);
      std::unique_ptr<const DexFile> dex_file;
      // 根据路径得到OatDexFile对象
      const OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(location, nullptr, error_msg);
      if (oat_dex_file == nullptr) {
        return std::unique_ptr<const DexFile>();
      }
      std::string inner_error_msg;
      // 根据地址找到dex_file结构 , 并且填充信息
      dex_file = oat_dex_file->OpenDexFile(&inner_error_msg);
      // 如果打开失败
      if (dex_file == nullptr) {
        *error_msg = StringPrintf("Failed to open dex file %s from within oat file %s error '%s'",
                                  location,
                                  oat_file->GetLocation().c_str(),
                                  inner_error_msg.c_str());
        return std::unique_ptr<const DexFile>();
      }
      // 校验失败
      if (dex_file->GetLocationChecksum() != oat_dex_file->GetDexFileLocationChecksum()) {
        *error_msg = StringPrintf("Checksums do not match for %s: %x vs %x",
                                  location,
                                  dex_file->GetLocationChecksum(),
                                  oat_dex_file->GetDexFileLocationChecksum());
        return std::unique_ptr<const DexFile>();
      }
      return dex_file;
    }
    
    1. OpenDexFile
    std::unique_ptr<const DexFile> OatFile::OatDexFile::OpenDexFile(std::string* error_msg) const {
      ScopedTrace trace(__PRETTY_FUNCTION__);
      static constexpr bool kVerify = false;
      static constexpr bool kVerifyChecksum = false;
      // oat文件中dex_file的指针
      return DexFile::Open(dex_file_pointer_,
                            // 整个文件大小
                           FileSize(),
                           // dex文件路径
                           dex_file_location_,
                           // dex文件路径的校验码
                           dex_file_location_checksum_,
                           this,
                           kVerify,
                           kVerifyChecksum,
                           error_msg);
    }
    
    1. OpenCommon
    std::unique_ptr<DexFile> DexFile::OpenCommon(const uint8_t* base,
                                                 size_t size,
                                                 const std::string& location,
                                                 uint32_t location_checksum,
                                                 const OatDexFile* oat_dex_file,
                                                 bool verify,
                                                 bool verify_checksum,
                                                 std::string* error_msg,
                                                 VerifyResult* verify_result) {
     // 通过dex_file基址初始化Dex_File  
      std::unique_ptr<DexFile> dex_file(new DexFile(base,
                                                    size,
                                                    location,
                                                    location_checksum,
                                                    oat_dex_file));
      ... 
      // 开始校验Dex
      if (verify && !DexFileVerifier::Verify(dex_file.get(),
                                             dex_file->Begin(),
                                             dex_file->Size(),
                                             location.c_str(),
                                             verify_checksum,
                                             error_msg)) {
        if (verify_result != nullptr) {
          *verify_result = VerifyResult::kVerifyFailed;
        }
        return nullptr;
      }
      if (verify_result != nullptr) {
        *verify_result = VerifyResult::kVerifySucceeded;
      }
      return dex_file;
    }
    
    
    1. DexFile构造函数
    DexFile::DexFile(const uint8_t* base,
                     size_t size,
                     const std::string& location,
                     uint32_t location_checksum,
                     const OatDexFile* oat_dex_file)
        : begin_(base),
          size_(size),
          location_(location),
          location_checksum_(location_checksum),
          // 初始化Header
          header_(reinterpret_cast<const Header*>(base)),
          // 初始化Stringid
          string_ids_(reinterpret_cast<const StringId*>(base + header_->string_ids_off_)),
          // 初始化type id
          type_ids_(reinterpret_cast<const TypeId*>(base + header_->type_ids_off_)),
          // 初始化filed_id
          field_ids_(reinterpret_cast<const FieldId*>(base + header_->field_ids_off_)),
          // 初始化method_id
          method_ids_(reinterpret_cast<const MethodId*>(base + header_->method_ids_off_)),
          proto_ids_(reinterpret_cast<const ProtoId*>(base + header_->proto_ids_off_)),
          // 初始化class_def
          class_defs_(reinterpret_cast<const ClassDef*>(base + header_->class_defs_off_)),
          method_handles_(nullptr),
          num_method_handles_(0),
          call_site_ids_(nullptr),
          num_call_site_ids_(0),
          oat_dex_file_(oat_dex_file) {
      // 初始化各个Section
      InitializeSectionsFromMapList();
    }
    
      
    void DexFile::InitializeSectionsFromMapList() {
      const MapList* map_list = reinterpret_cast<const MapList*>(begin_ + header_->map_off_);
      if (header_->map_off_ == 0 || header_->map_off_ > size_) {
        // Bad offset. The dex file verifier runs after this method and will reject the file.
        return;
      }
      const size_t count = map_list->size_;
      // 得到Map大小
      size_t map_limit = header_->map_off_ + count * sizeof(MapItem);
      if (header_->map_off_ >= map_limit || map_limit > size_) {
        // Overflow or out out of bounds. The dex file verifier runs after
        // this method and will reject the file as it is malformed.
        return;
      }
    
      for (size_t i = 0; i < count; ++i) {
        // 遍历所有的Section
        const MapItem& map_item = map_list->list_[i];
        if (map_item.type_ == kDexTypeMethodHandleItem) {
          // 如果maptype为Method句柄的话
          // 其中begin_也就是base , 基址
          method_handles_ = reinterpret_cast<const MethodHandleItem*>(begin_ + map_item.offset_);
          num_method_handles_ = map_item.size_;
        } else if (map_item.type_ == kDexTypeCallSiteIdItem) {
          call_site_ids_ = reinterpret_cast<const CallSiteIdItem*>(begin_ + map_item.offset_);
          num_call_site_ids_ = map_item.size_;
        }
      }
    }
    
    }
    

    12.DexFileVerifier::Verify校验Dex文件

    bool DexFileVerifier::Verify() {
      // Check the header.
      if (!CheckHeader()) {
        return false;
      }
    
      // Check the map section.
      if (!CheckMap()) {
        return false;
      }
    
      // Check structure within remaining sections.
      if (!CheckIntraSection()) {
        return false;
      }
    
      // Check references from one section to another.
      if (!CheckInterSection()) {
        return false;
      }
    
      return true;
    }
    
    
    1. ElfOatFile , 由于在Linux平台上 , 所以对应的oat_file类型为ElfOatFile
    ElfOatFile* ElfOatFile::OpenElfFile(File* file,
                                        const std::string& location,
                                        uint8_t* requested_base,
                                        uint8_t* oat_file_begin,  // Override base if not null
                                        bool writable,
                                        bool executable,
                                        bool low_4gb,
                                        const char* abs_dex_location,
                                        std::string* error_msg) {
      ScopedTrace trace("Open elf file " + location);
      std::unique_ptr<ElfOatFile> oat_file(new ElfOatFile(location, executable));
      bool success = oat_file->ElfFileOpen(file,
                                           oat_file_begin,
                                           writable,
                                           low_4gb,
                                           executable,
                                           error_msg);
      if (!success) {
        CHECK(!error_msg->empty());
        return nullptr;
      }
    

    相关文章

      网友评论

          本文标题:PathClassLoader加载与查找类

          本文链接:https://www.haomeiwen.com/subject/tkmjektx.html