爲什麼編譯時方法過多會出現method ID not in [0, 0xffff]: 65536的錯誤

隨着項目的功能增多,產品框架也會越來越大,要實現的邏輯也會更多,遇到method個數超出65536個這個問題幾乎是每一個Android碼農必有的經歷,我們一直忙於解決問題,可能這個問題百度一下即可解決,卻沒有真正去探知究竟。最近我學習熱修復的過程中,再次遇到這個問題,特分析一下爲什麼會出現method個數超出65536個而導致編譯失敗問題,以作記錄。

由於無論android-19出現的art,還是之前的dalvik,對Dex文件的定義中,都將方法大小的定義uint32_t類型(uint32_t包含8個字節),直接決定了每個Dex文件的方法數不能超過65536個。

dalvik虛擬機對Dex文件的定義(部分):

libdex/DexFile.h(dalvik):

/*
 * Direct-mapped "header_item" struct.
 */
struct DexHeader {
    u1  magic[8];           /* includes version number */
    u4  checksum;           /* adler32 checksum */
    u1  signature[kSHA1DigestLen]; /* SHA-1 hash */
    u4  fileSize;           /* length of entire file */
    u4  headerSize;         /* offset to start of next section */
    u4  endianTag;
    u4  linkSize;
    u4  linkOff;
    u4  mapOff;
    u4  stringIdsSize;
    u4  stringIdsOff;
    u4  typeIdsSize;
    u4  typeIdsOff;
    u4  protoIdsSize;
    u4  protoIdsOff;
    u4  fieldIdsSize;
    u4  fieldIdsOff;
    u4  methodIdsSize; /* methodIdsSize是u4類型,而u4從uint32_t聲明定義的,8個字節的限制導致了此錯誤*/
    u4  methodIdsOff;
    u4  classDefsSize;
    u4  classDefsOff;
    u4  dataSize;
    u4  dataOff;
};

vm/Common.h

/*
 * These match the definitions in the VM specification.
 */
typedef uint8_t             u1;
typedef uint16_t            u2;
typedef uint32_t            u4;
typedef uint64_t            u8;
typedef int8_t              s1;
typedef int16_t             s2;
typedef int32_t             s4;
typedef int64_t             s8;


art虛擬機對dex文件的定義(部分)

runtime/dex_file.h(art):

  // Raw header_item.
  struct Header {
    uint8_t magic_[8];
    uint32_t checksum_;  // See also location_checksum_
    uint8_t signature_[kSha1DigestSize];
    uint32_t file_size_;  // size of entire file
    uint32_t header_size_;  // offset to start of next section
    uint32_t endian_tag_;
    uint32_t link_size_;  // unused
    uint32_t link_off_;  // unused
    uint32_t map_off_;  // unused
    uint32_t string_ids_size_;  // number of StringIds
    uint32_t string_ids_off_;  // file offset of StringIds array
    uint32_t type_ids_size_;  // number of TypeIds, we don't support more than 65535
    uint32_t type_ids_off_;  // file offset of TypeIds array
    uint32_t proto_ids_size_;  // number of ProtoIds, we don't support more than 65535
    uint32_t proto_ids_off_;  // file offset of ProtoIds array
    uint32_t field_ids_size_;  // number of FieldIds
    uint32_t field_ids_off_;  // file offset of FieldIds array
    uint32_t method_ids_size_;  // number of MethodIds
    uint32_t method_ids_off_;  // file offset of MethodIds array
    uint32_t class_defs_size_;  // number of ClassDefs
    uint32_t class_defs_off_;  // file offset of ClassDef array
    uint32_t data_size_;  // unused
    uint32_t data_off_;  // unused
    // Decode the dex magic version
    uint32_t GetVersion() const;
   private:
    DISALLOW_COPY_AND_ASSIGN(Header);
  };



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章