前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >PathClassLoader加载与查找类

PathClassLoader加载与查找类

作者头像
None_Ling
发布2020-09-14 14:20:04
1.8K0
发布2020-09-14 14:20:04
举报
文章被收录于专栏:Android相关Android相关

简述

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

代码语言:javascript
复制
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的

代码语言:javascript
复制
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对象
代码语言:javascript
复制
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数组中
代码语言:javascript
复制
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
代码语言:javascript
复制
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的指针
代码语言:javascript
复制
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层
代码语言:javascript
复制
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重新尝试加载一次
代码语言:javascript
复制
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
代码语言:javascript
复制
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
代码语言:javascript
复制
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
代码语言:javascript
复制
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
代码语言:javascript
复制
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构造函数
代码语言:javascript
复制
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文件

代码语言:javascript
复制
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
代码语言:javascript
复制
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;
  }
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 简述
  • PathClassLoader
  • BaseDexClassLoader
  • DexPathList
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档