http://www.cnblogs.com/yydcdut/p/4887157.html
這篇看過,雖然通篇中文,不過處處難懂 Orz
1.為什麼 method count 不得多於 64K?
從前 x86 時代,我是有學機械語言及組合語言的
所以對於一個 function 不能大於多少 size 可以理解
原因就是一個 jmp 或 call 指令,其後只帶幾個 byte
(如果只帶一個,限制就在 256 byte, 帶兩個,限制就在 65536 byte)
而 x86架構下有所謂"段暫存器"(哇塞,考古到這超懷念)
因此如果只用兩個 byte 來表達位址,那就是段內跳躍
只用一個 byte,常見的不是絕對定址
(取出目前這道指令的位址,把它 16位元的 hibyte 留著,
lobyte 改以 jmp 後帶的一個 byte 取代)
而是相對定址
(取出目前指令位址,加上 jmp 後帶的一個 byte,
而且這個 byte 是當成 signed,有正負號的,因此可以往前後跳 127 byte)
更大的則是帶四個 byte, 那就可以做32位元跳躍
至於以前雖然有 32 位元位址觀念,但其實只有 20條位址線
這種偷吃步引起的奇怪限制,討論就更多了
我們其實都是跟著 compiler 給的架構一起成長 XDDDD
本來想詳述這段,但一來離題,二來無法講得乾淨
跳回 android dex 繼續談:
我明明看 java 編出來的 code 裡面有一堆 function name
(因此亂恐怖的,如果不攪拌一下,根本可以從執行檔反組譯出程式來)
所以我認為它的 function call 實現方式,應該就是直接去 mapping function name 吧!
字串能有多少變化,funtion 就能有多少,不是嗎?
java 又沒把指令 compile 完後,變成只是個數字
fun1
fun2
fun3
.
.
.
fun65536
像上面那樣,如果真的指令只能用數字 access,那我就理解它指令數只能有 64K 個
可是比如 reflect function,都是用 function name 把函式指標取出來
看來即使編譯成了執行檔,function name 也沒被丟掉
這種定址法其實很像 win 之下的 DLL, 可以用 GetProcAddress
https://msdn.microsoft.com/en-us/library/windows/desktop/ms683212(v=vs.85).aspx
它傳入的參數可是字串,是 function name
那怎麼會有 64K 限制?
或許 Java 是允許用 function name 定址
但無論如何它內部就是非得用 function number 來呼叫
(可能是這樣可以寫 table, 不用一直做字串比對,速度會比較快?)
好吧,那就先接受這個限制(反正我又寫不出 compiler,我不接受也不行)
但切 multidex 我又會有另一個問題
2.若我用 DLL 來理解 dex 的話
那不只是要把太大的程式切成兩個 dex
而且,兩個 dex 間,還不得互相呼叫
比如,若我的程式已經有 65538 個函式(就是只多兩個)
那並不是切成相等的兩塊,每塊 32769 個函式就好
而是,第一個 dex 的函式,都不能去呼叫第二個 dex 的函式
因為有定址空間誤會的問題
如果切出一個 main-dex
然後由它載入 dex1 (function 相加總數不能超過 64K)
等要使用 dex2 時,dex1 還得退出
(這時 main-dec 加 dex2 function 總數還是不能超過 64K)
那我就懂了
(喔,那就和 win 下寫 dll 的問題一樣了)