dex文件格式
文件頭(File Header)
Dex文件頭主要包括校驗(yàn)和以及其他結(jié)構(gòu)的偏移地址和長度信息。
| magic | 0x0 | 8 | 'Magic'值,即魔數(shù)字段,格式如”dex/n035/0”,其中的035表示結(jié)構(gòu)的版本。 |
| checksum | 0x8 | 4 | 校驗(yàn)碼。 |
| signature | 0xC | 20 | SHA-1簽名。 |
| file_size | 0x20 | 4 | Dex文件的總長度。 |
| header_size | 0x24 | 4 | 文件頭長度,009版本=0x5C,035版本=0x70。 |
| endian_tag | 0x28 | 4 | 標(biāo)識(shí)字節(jié)順序的常量,根據(jù)這個(gè)常量可以判斷文件是否交換了字節(jié)順序,缺省情況下=0x78563412。 |
| link_size | 0x2C | 4 | 連接段的大小,如果為0就表示是靜態(tài)連接。 |
| link_off | 0x30 | 4 | 連接段的開始位置,從本文件頭開始算起。如果連接段的大小為0,這里也是0。 |
| map_off | 0x34 | 4 | map數(shù)據(jù)基地址。 |
| string_ids_size | 0x38 | 4 | 字符串列表的字符串個(gè)數(shù)。 |
| string_ids_off | 0x3C | 4 | 字符串列表表基地址。 |
| type_ids_size | 0x40 | 4 | 類型列表里類型個(gè)數(shù)。 |
| type_ids_off | 0x44 | 4 | 類型列表基地址。 |
| proto_ids_size | 0x48 | 4 | 原型列表里原型個(gè)數(shù)。 |
| proto_ids_off | 0x4C | 4 | 原型列表基地址。 |
| field_ids_size | 0x50 | 4 | 字段列表里字段個(gè)數(shù)。 |
| field_ids_off | 0x54 | 4 | 字段列表基地址。 |
| method_ids_size | 0x58 | 4 | 方法列表里方法個(gè)數(shù)。 |
| method_ids_off | 0x5C | 4 | 方法列表基地址。 |
| class_defs_size | 0x60 | 4 | 類定義類表中類的個(gè)數(shù)。 |
| class_defs_off | 0x64 | 4 | 類定義列表基地址。 |
| data_size | 0x68 | 4 | 數(shù)據(jù)段的大小,必須以4字節(jié)對齊。 |
| data_off | 0x6C | 4 | 數(shù)據(jù)段基地址 |
魔數(shù)字段
? ? ?魔數(shù)字段,主要就是Dex文件的標(biāo)識(shí)符,它占用4個(gè)字節(jié),在目前的源碼里是 “dex\n”,它的作用主要是用來標(biāo)識(shí)dex文件的,比如有一個(gè)文件也以dex為后綴名,僅此并不會(huì)被認(rèn)為是Davlik虛擬機(jī)運(yùn)行的文件,還要判斷這 四個(gè)字節(jié)。另外Davlik虛擬機(jī)也有優(yōu)化的Dex,也是通過個(gè)字段來區(qū)分的,當(dāng)它是優(yōu)化的Dex文件時(shí),它的值就變成”dey\n”了。根據(jù)這四個(gè)字 節(jié),就可以識(shí)別不同類型的Dex文件了。
? ? ? 跟在“dex\n”后面的是版本字段,主要用來標(biāo)識(shí)Dex文件的版本。目前支持的版本號(hào)為“035\0”,不管是否優(yōu)化的版本,都是使用這個(gè)版本號(hào)。
檢驗(yàn)碼字段? ? ?主要用來檢查從這個(gè)字段開始到文件結(jié)尾,這段數(shù)據(jù)是否完整,有沒有人修改過,或者傳送過程中是否有出錯(cuò)等等。通常用來檢查數(shù)據(jù)是否完整的算法,有 CRC32、有SHA128等,但這里采用并不是這兩類,而采用一個(gè)比較特別的算法,叫做adler32,這是在開源zlib里常用的算法,用來檢查文件 是否完整性。該算法由MarkAdler發(fā)明,其可靠程度跟CRC32差不多,不過還是弱一點(diǎn)點(diǎn),但它有一個(gè)很好的優(yōu)點(diǎn),就是使用軟件來計(jì)算檢驗(yàn)碼時(shí)比較 CRC32要快很多。可見Android系統(tǒng),就算法上就已經(jīng)為移動(dòng)設(shè)備進(jìn)行優(yōu)化了。
? ? ?Java中可使用java.util.zip.Adler32類做校驗(yàn)操作
SHA-1簽名字段
? ? ?dex文件頭里,前面已經(jīng)有了面有一個(gè)4字節(jié)的檢驗(yàn)字段碼了,為什么還會(huì)有SHA-1簽名字段呢?不是重復(fù)了嗎?可是仔細(xì)考慮一下,這樣設(shè)計(jì)自有道理。因 為dex文件一般都不是很小,簡單的應(yīng)用程序都有幾十K,這么多數(shù)據(jù)使用一個(gè)4字節(jié)的檢驗(yàn)碼,重復(fù)的機(jī)率還是有的,也就是說當(dāng)文件里的數(shù)據(jù)修改了,還是很 有可能檢驗(yàn)不出來的。這時(shí)檢驗(yàn)碼就失去了作用,需要使用更加強(qiáng)大的檢驗(yàn)碼,這就是SHA-1。SHA-1校驗(yàn)碼有20個(gè)字節(jié),比前面的檢驗(yàn)碼多了16個(gè)字 節(jié),幾乎不會(huì)不同的文件計(jì)算出來的檢驗(yàn)是一樣的。設(shè)計(jì)兩個(gè)檢驗(yàn)碼的目的,就是先使用第一個(gè)檢驗(yàn)碼進(jìn)行快速檢查,這樣可以先把簡單出錯(cuò)的dex文件丟掉了, 接著再使用第二個(gè)復(fù)雜的檢驗(yàn)碼進(jìn)行復(fù)雜計(jì)算,驗(yàn)證文件是否完整,這樣確保執(zhí)行的文件完整和安全。
? ? ? SHA(Secure Hash Algorithm, 安全散列算法)是美國國家安全局設(shè)計(jì),美國國家標(biāo)準(zhǔn)與技術(shù)研究院發(fā)布的一系列密碼散列函數(shù)。SHA-1看起來和MD5算法很像,也許是Ron Rivest在SHA-1的設(shè)計(jì)中起了一定的作用。SHA-1的內(nèi)部比MD5更強(qiáng),其摘要比MD5的16字節(jié)長4個(gè)字節(jié),這個(gè)算法成功經(jīng)受了密碼分析專家 的攻擊,也因而受到密碼學(xué)界的廣泛推崇。這個(gè)算法在目前網(wǎng)絡(luò)上的簽名,BT軟件里就有大量使用,比如在BT里要計(jì)算是否同一個(gè)種子時(shí),就是利用文件的簽名 來判斷的。同一份8G的電影從幾千BT用戶那里下載,也不會(huì)出現(xiàn)錯(cuò)誤的數(shù)據(jù),導(dǎo)致電影不播放。
map_off字段
這個(gè)字段主要保存map開始位置,就是從文件頭開始到map數(shù)據(jù)的長度,通過這個(gè)索引就可以找到map數(shù)據(jù)。map的數(shù)據(jù)結(jié)構(gòu)如下:
| size | 4字節(jié) | map里項(xiàng)的個(gè)數(shù) |
| list | 變長 | 每一項(xiàng)定義為12字節(jié),項(xiàng)的個(gè)數(shù)由上面項(xiàng)大小決定。 |
map數(shù)據(jù)排列結(jié)構(gòu)定義如下:
<span class="coMULTI" style="line-height: 20px;">/* *Direct-mapped "map_list". */</span><span class="kw4" style="line-height: 20px;">typedef</span> <span class="kw4" style="line-height: 20px;">struct</span> DexMapList <span class="br0" style="line-height: 20px;">{</span>u4 size<span class="sy0" style="line-height: 20px;">;</span> <span class="coMULTI" style="line-height: 20px;">/* #of entries inlist */</span>DexMapItem list<span class="br0" style="line-height: 20px;">[</span><span class="nu0" style="line-height: 20px;">1</span><span class="br0" style="line-height: 20px;">]</span><span class="sy0" style="line-height: 20px;">;</span> <span class="coMULTI" style="line-height: 20px;">/* entries */</span> <span class="br0" style="line-height: 20px;">}</span>DexMapList<span class="sy0" style="line-height: 20px;">;</span>每一個(gè)map項(xiàng)的結(jié)構(gòu)定義如下:
<span class="coMULTI" style="line-height: 20px;">/* *Direct-mapped "map_item". */</span><span class="kw4" style="line-height: 20px;">typedef</span> <span class="kw4" style="line-height: 20px;">struct</span> DexMapItem <span class="br0" style="line-height: 20px;">{</span>u2 type<span class="sy0" style="line-height: 20px;">;</span> <span class="coMULTI" style="line-height: 20px;">/* type code (seekDexType* above) */</span>u2 unused<span class="sy0" style="line-height: 20px;">;</span>u4 size<span class="sy0" style="line-height: 20px;">;</span> <span class="coMULTI" style="line-height: 20px;">/* count of items ofthe indicated type */</span>u4 offset<span class="sy0" style="line-height: 20px;">;</span> <span class="coMULTI" style="line-height: 20px;">/* file offset tothe start of data */</span> <span class="br0" style="line-height: 20px;">}</span>DexMapItem<span class="sy0" style="line-height: 20px;">;</span>DexMapItem結(jié)構(gòu)定義每一項(xiàng)的數(shù)據(jù)意義:類型、類型個(gè)數(shù)、類型開始位置。
其中的類型定義如下:
<span class="coMULTI" style="line-height: 20px;">/*map item type codes */</span> <span class="kw2" style="line-height: 20px;">enum</span><span class="br0" style="line-height: 20px;">{</span>kDexTypeHeaderItem <span class="sy0" style="line-height: 20px;">=</span> <span class="nu12" style="line-height: 20px;">0x0000</span><span class="sy0" style="line-height: 20px;">,</span>kDexTypeStringIdItem <span class="sy0" style="line-height: 20px;">=</span> <span class="nu12" style="line-height: 20px;">0x0001</span><span class="sy0" style="line-height: 20px;">,</span>kDexTypeTypeIdItem <span class="sy0" style="line-height: 20px;">=</span> <span class="nu12" style="line-height: 20px;">0x0002</span><span class="sy0" style="line-height: 20px;">,</span>kDexTypeProtoIdItem <span class="sy0" style="line-height: 20px;">=</span> <span class="nu12" style="line-height: 20px;">0x0003</span><span class="sy0" style="line-height: 20px;">,</span>kDexTypeFieldIdItem <span class="sy0" style="line-height: 20px;">=</span> <span class="nu12" style="line-height: 20px;">0x0004</span><span class="sy0" style="line-height: 20px;">,</span>kDexTypeMethodIdItem <span class="sy0" style="line-height: 20px;">=</span> <span class="nu12" style="line-height: 20px;">0x0005</span><span class="sy0" style="line-height: 20px;">,</span>kDexTypeClassDefItem <span class="sy0" style="line-height: 20px;">=</span> <span class="nu12" style="line-height: 20px;">0x0006</span><span class="sy0" style="line-height: 20px;">,</span>kDexTypeMapList <span class="sy0" style="line-height: 20px;">=</span> <span class="nu12" style="line-height: 20px;">0x1000</span><span class="sy0" style="line-height: 20px;">,</span>kDexTypeTypeList <span class="sy0" style="line-height: 20px;">=</span> <span class="nu12" style="line-height: 20px;">0x1001</span><span class="sy0" style="line-height: 20px;">,</span>kDexTypeAnnotationSetRefList <span class="sy0" style="line-height: 20px;">=</span> <span class="nu12" style="line-height: 20px;">0x1002</span><span class="sy0" style="line-height: 20px;">,</span>kDexTypeAnnotationSetItem <span class="sy0" style="line-height: 20px;">=</span> <span class="nu12" style="line-height: 20px;">0x1003</span><span class="sy0" style="line-height: 20px;">,</span>kDexTypeClassDataItem <span class="sy0" style="line-height: 20px;">=</span> <span class="nu12" style="line-height: 20px;">0x2000</span><span class="sy0" style="line-height: 20px;">,</span>kDexTypeCodeItem <span class="sy0" style="line-height: 20px;">=</span> <span class="nu12" style="line-height: 20px;">0x2001</span><span class="sy0" style="line-height: 20px;">,</span>kDexTypeStringDataItem <span class="sy0" style="line-height: 20px;">=</span> <span class="nu12" style="line-height: 20px;">0x2002</span><span class="sy0" style="line-height: 20px;">,</span>kDexTypeDebugInfoItem <span class="sy0" style="line-height: 20px;">=</span> <span class="nu12" style="line-height: 20px;">0x2003</span><span class="sy0" style="line-height: 20px;">,</span>kDexTypeAnnotationItem <span class="sy0" style="line-height: 20px;">=</span> <span class="nu12" style="line-height: 20px;">0x2004</span><span class="sy0" style="line-height: 20px;">,</span>kDexTypeEncodedArrayItem <span class="sy0" style="line-height: 20px;">=</span> <span class="nu12" style="line-height: 20px;">0x2005</span><span class="sy0" style="line-height: 20px;">,</span>kDexTypeAnnotationsDirectoryItem <span class="sy0" style="line-height: 20px;">=</span> <span class="nu12" style="line-height: 20px;">0x2006</span><span class="sy0" style="line-height: 20px;">,</span> <span class="br0" style="line-height: 20px;">}</span><span class="sy0" style="line-height: 20px;">;</span>從上面的類型可知,它包括了在dex文件里可能出現(xiàn)的所有類型。可以看出這里的類型與文件頭里定義的類型有很多是一樣的,這里的類型其實(shí)就是文件頭里定義 的類型。其實(shí)這個(gè)map的數(shù)據(jù),就是頭里類型的重復(fù),完全是為了檢驗(yàn)作用而存在的。當(dāng)Android系統(tǒng)加載dex文件時(shí),如果比較文件頭類型個(gè)數(shù)與 map里類型不一致時(shí),就會(huì)停止使用這個(gè)dex文件
string_ids_size/off字段
這兩個(gè)字段主要用來標(biāo)識(shí)字符串資源。源程序編譯后,程序里用到的字符串都保存在這個(gè)數(shù)據(jù)段里,以便解釋執(zhí)行這個(gè)dex文件使用。其中包括調(diào)用庫函數(shù)里的類名稱描述,用于輸出顯示的字符串等。
string_ids_size標(biāo)識(shí)了有多少個(gè)字符串,string_ids_off標(biāo)識(shí)字符串?dāng)?shù)據(jù)區(qū)的開始位置。字符串的存儲(chǔ)結(jié)構(gòu)如下:
<span class="coMULTI" style="line-height: 20px;">/** Direct-mapped "string_id_item".*/</span> <span class="kw4" style="line-height: 20px;">typedef</span> <span class="kw4" style="line-height: 20px;">struct</span> DexStringId <span class="br0" style="line-height: 20px;">{</span>u4 stringDataOff<span class="sy0" style="line-height: 20px;">;</span> <span class="coMULTI" style="line-height: 20px;">/* file offset to string_data_item */</span> <span class="br0" style="line-height: 20px;">}</span> DexStringId<span class="sy0" style="line-height: 20px;">;</span>可以看出這個(gè)數(shù)據(jù)區(qū)保存的只是字符串表的地址索引。如果要找到字符串的實(shí)際數(shù)據(jù),還需要通過個(gè)地址索引找到文件的相應(yīng)開始位置,然后才能得到字符串?dāng)?shù)據(jù)。 每一個(gè)字符串項(xiàng)的索引占用4個(gè)字節(jié),因此這個(gè)數(shù)據(jù)區(qū)的大小就為4*string_ids_size。實(shí)際數(shù)據(jù)區(qū)中的字符串采用UTF8格式保存。
例如,如果dex文件使用16進(jìn)制顯示出來內(nèi)容如下:
063c 696e 6974 3e00
其實(shí)際數(shù)據(jù)則是”<init>\0”
另外這段數(shù)據(jù)中不僅包括字符串的字符串的內(nèi)容和結(jié)束標(biāo)志,在最開頭的位置還標(biāo)明了字符串的長度。上例中第一個(gè)字節(jié)06就是表示這個(gè)字符串有6個(gè)字符。
關(guān)于字符串的長度有兩點(diǎn)需要注意的地方:
1、關(guān)于長度的編碼格式
dex文件里采用了變長方式表示字符串長度。一個(gè)字符串的長度可能是一個(gè)字節(jié)(小于256)或者4個(gè)字節(jié)(1G大小以上)。字符串的長度大多數(shù)都是小于 256個(gè)字節(jié),因此需要使用一種編碼,既可以表示一個(gè)字節(jié)的長度,也可以表示4個(gè)字節(jié)的長度,并且1個(gè)字節(jié)的長度占絕大多數(shù)。能滿足這種表示的編碼方式有 很多,但dex文件里采用的是uleb128方式。leb128編碼是一種變長編碼,每個(gè)字節(jié)采用7位來表達(dá)原來的數(shù)據(jù),最高位用來表示是否有后繼字節(jié)。
它的編碼算法如下:
<span class="coMULTI" style="line-height: 20px;">/** Writes a 32-bit value in unsigned ULEB128 format.* Returns the updated pointer.*/</span> DEX_INLINE u1<span class="sy0" style="line-height: 20px;">*</span> writeUnsignedLeb128<span class="br0" style="line-height: 20px;">(</span>u1<span class="sy0" style="line-height: 20px;">*</span> ptr<span class="sy0" style="line-height: 20px;">,</span> u4 data<span class="br0" style="line-height: 20px;">)</span> <span class="br0" style="line-height: 20px;">{</span><span class="kw1" style="line-height: 20px;">while</span> <span class="br0" style="line-height: 20px;">(</span><span class="kw2" style="line-height: 20px;">true</span><span class="br0" style="line-height: 20px;">)</span> <span class="br0" style="line-height: 20px;">{</span>u1 out <span class="sy0" style="line-height: 20px;">=</span> data <span class="sy0" style="line-height: 20px;">&</span> <span class="nu12" style="line-height: 20px;">0x7f</span><span class="sy0" style="line-height: 20px;">;</span><span class="kw1" style="line-height: 20px;">if</span> <span class="br0" style="line-height: 20px;">(</span>out <span class="sy0" style="line-height: 20px;">!=</span> data<span class="br0" style="line-height: 20px;">)</span> <span class="br0" style="line-height: 20px;">{</span><span class="sy0" style="line-height: 20px;">*</span>ptr<span class="sy0" style="line-height: 20px;">++</span> <span class="sy0" style="line-height: 20px;">=</span> out <span class="sy0" style="line-height: 20px;">|</span> <span class="nu12" style="line-height: 20px;">0x80</span><span class="sy0" style="line-height: 20px;">;</span>data <span class="sy0" style="line-height: 20px;">>>=</span> <span class="nu0" style="line-height: 20px;">7</span><span class="sy0" style="line-height: 20px;">;</span><span class="br0" style="line-height: 20px;">}</span> <span class="kw1" style="line-height: 20px;">else</span> <span class="br0" style="line-height: 20px;">{</span><span class="sy0" style="line-height: 20px;">*</span>ptr<span class="sy0" style="line-height: 20px;">++</span> <span class="sy0" style="line-height: 20px;">=</span> out<span class="sy0" style="line-height: 20px;">;</span><span class="kw2" style="line-height: 20px;">break</span><span class="sy0" style="line-height: 20px;">;</span><span class="br0" style="line-height: 20px;">}</span><span class="br0" style="line-height: 20px;">}</span><span class="kw1" style="line-height: 20px;">return</span> ptr<span class="sy0" style="line-height: 20px;">;</span> <span class="br0" style="line-height: 20px;">}</span>它的解碼算法如下:
<span class="coMULTI" style="line-height: 20px;">/** Reads an unsigned LEB128 value, updating the given pointer to point* just past the end of the read value. This function tolerates* non-zero high-order bits in the fifth encoded byte.*/</span> DEX_INLINE <span class="kw4" style="line-height: 20px;">int</span> readUnsignedLeb128<span class="br0" style="line-height: 20px;">(</span><span class="kw4" style="line-height: 20px;">const</span> u1<span class="sy0" style="line-height: 20px;">**</span> pStream<span class="br0" style="line-height: 20px;">)</span> <span class="br0" style="line-height: 20px;">{</span><span class="kw4" style="line-height: 20px;">const</span> u1<span class="sy0" style="line-height: 20px;">*</span> ptr <span class="sy0" style="line-height: 20px;">=</span> <span class="sy0" style="line-height: 20px;">*</span>pStream<span class="sy0" style="line-height: 20px;">;</span><span class="kw4" style="line-height: 20px;">int</span> result <span class="sy0" style="line-height: 20px;">=</span> <span class="sy0" style="line-height: 20px;">*</span><span class="br0" style="line-height: 20px;">(</span>ptr<span class="sy0" style="line-height: 20px;">++</span><span class="br0" style="line-height: 20px;">)</span><span class="sy0" style="line-height: 20px;">;</span><span class="kw1" style="line-height: 20px;">if</span> <span class="br0" style="line-height: 20px;">(</span>result <span class="sy0" style="line-height: 20px;">></span> <span class="nu12" style="line-height: 20px;">0x7f</span><span class="br0" style="line-height: 20px;">)</span> <span class="br0" style="line-height: 20px;">{</span><span class="kw4" style="line-height: 20px;">int</span> cur <span class="sy0" style="line-height: 20px;">=</span> <span class="sy0" style="line-height: 20px;">*</span><span class="br0" style="line-height: 20px;">(</span>ptr<span class="sy0" style="line-height: 20px;">++</span><span class="br0" style="line-height: 20px;">)</span><span class="sy0" style="line-height: 20px;">;</span>result <span class="sy0" style="line-height: 20px;">=</span> <span class="br0" style="line-height: 20px;">(</span>result <span class="sy0" style="line-height: 20px;">&</span> <span class="nu12" style="line-height: 20px;">0x7f</span><span class="br0" style="line-height: 20px;">)</span> <span class="sy0" style="line-height: 20px;">|</span> <span class="br0" style="line-height: 20px;">(</span><span class="br0" style="line-height: 20px;">(</span>cur <span class="sy0" style="line-height: 20px;">&</span> <span class="nu12" style="line-height: 20px;">0x7f</span><span class="br0" style="line-height: 20px;">)</span> <span class="sy0" style="line-height: 20px;"><<</span> <span class="nu0" style="line-height: 20px;">7</span><span class="br0" style="line-height: 20px;">)</span><span class="sy0" style="line-height: 20px;">;</span><span class="kw1" style="line-height: 20px;">if</span> <span class="br0" style="line-height: 20px;">(</span>cur <span class="sy0" style="line-height: 20px;">></span> <span class="nu12" style="line-height: 20px;">0x7f</span><span class="br0" style="line-height: 20px;">)</span> <span class="br0" style="line-height: 20px;">{</span>cur <span class="sy0" style="line-height: 20px;">=</span> <span class="sy0" style="line-height: 20px;">*</span><span class="br0" style="line-height: 20px;">(</span>ptr<span class="sy0" style="line-height: 20px;">++</span><span class="br0" style="line-height: 20px;">)</span><span class="sy0" style="line-height: 20px;">;</span>result <span class="sy0" style="line-height: 20px;">|=</span> <span class="br0" style="line-height: 20px;">(</span>cur <span class="sy0" style="line-height: 20px;">&</span> <span class="nu12" style="line-height: 20px;">0x7f</span><span class="br0" style="line-height: 20px;">)</span> <span class="sy0" style="line-height: 20px;"><<</span> <span class="nu0" style="line-height: 20px;">14</span><span class="sy0" style="line-height: 20px;">;</span><span class="kw1" style="line-height: 20px;">if</span> <span class="br0" style="line-height: 20px;">(</span>cur <span class="sy0" style="line-height: 20px;">></span> <span class="nu12" style="line-height: 20px;">0x7f</span><span class="br0" style="line-height: 20px;">)</span> <span class="br0" style="line-height: 20px;">{</span>cur <span class="sy0" style="line-height: 20px;">=</span> <span class="sy0" style="line-height: 20px;">*</span><span class="br0" style="line-height: 20px;">(</span>ptr<span class="sy0" style="line-height: 20px;">++</span><span class="br0" style="line-height: 20px;">)</span><span class="sy0" style="line-height: 20px;">;</span>result <span class="sy0" style="line-height: 20px;">|=</span> <span class="br0" style="line-height: 20px;">(</span>cur <span class="sy0" style="line-height: 20px;">&</span> <span class="nu12" style="line-height: 20px;">0x7f</span><span class="br0" style="line-height: 20px;">)</span> <span class="sy0" style="line-height: 20px;"><<</span> <span class="nu0" style="line-height: 20px;">21</span><span class="sy0" style="line-height: 20px;">;</span><span class="kw1" style="line-height: 20px;">if</span> <span class="br0" style="line-height: 20px;">(</span>cur <span class="sy0" style="line-height: 20px;">></span> <span class="nu12" style="line-height: 20px;">0x7f</span><span class="br0" style="line-height: 20px;">)</span> <span class="br0" style="line-height: 20px;">{</span><span class="coMULTI" style="line-height: 20px;">/** Note: We don't check to see if cur is out of* range here, meaning we tolerate garbage in the* high four-order bits.*/</span>cur <span class="sy0" style="line-height: 20px;">=</span> <span class="sy0" style="line-height: 20px;">*</span><span class="br0" style="line-height: 20px;">(</span>ptr<span class="sy0" style="line-height: 20px;">++</span><span class="br0" style="line-height: 20px;">)</span><span class="sy0" style="line-height: 20px;">;</span>result <span class="sy0" style="line-height: 20px;">|=</span> cur <span class="sy0" style="line-height: 20px;"><<</span> <span class="nu0" style="line-height: 20px;">28</span><span class="sy0" style="line-height: 20px;">;</span><span class="br0" style="line-height: 20px;">}</span><span class="br0" style="line-height: 20px;">}</span><span class="br0" style="line-height: 20px;">}</span><span class="br0" style="line-height: 20px;">}</span><span class="sy0" style="line-height: 20px;">*</span>pStream <span class="sy0" style="line-height: 20px;">=</span> ptr<span class="sy0" style="line-height: 20px;">;</span><span class="kw1" style="line-height: 20px;">return</span> result<span class="sy0" style="line-height: 20px;">;</span> <span class="br0" style="line-height: 20px;">}</span>根據(jù)上面的算法分析上面例子字符串,取得第一個(gè)字節(jié)是06,最高位為0,因此沒有后繼字節(jié),那么取出這個(gè)字節(jié)里7位有效數(shù)據(jù),就是6,也就是說這個(gè)字符串是6個(gè)字節(jié),但不包括結(jié)束字符“\0”。
2、關(guān)于長度的意義
由于字符串內(nèi)容采用的是UTF-8格式編碼,表示一個(gè)字符的字節(jié)數(shù)是不定的。即有時(shí)是一個(gè)字節(jié)表示一個(gè)字符,有時(shí)是兩個(gè)、三個(gè)甚至四個(gè)字節(jié)表示一個(gè)字符。 而這里的長度代表的并不是整個(gè)字符串所占用的字節(jié)數(shù),表示這個(gè)字符串包含的字符個(gè)數(shù)。所以在讀取時(shí)需要注意,尤其是在包含中文字符時(shí),往往會(huì)因?yàn)樽x取的長 度不正確導(dǎo)致字符串被截?cái)唷?/p>
總結(jié)
- 上一篇: Dalvik指令集 (smali汇编)
- 下一篇: 静态分析android代码, 循环与tr