multidex 討論

作者: HuangJC (吹笛牧童)   2016-06-23 12:44:34
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 的問題一樣了)
作者: LPH66 (-6.2598534e+18f)   2016-06-23 13:45:00
64K 是 dex 的指令集設計上的問題其實 java 的 bytecode 本來也是有這限制的invokevirtual 後面跟的數字也是最大 64K但 java class 的函數計數只限於單一 class所以除非是超巨型 class 不然應該不會碰到但 dex 是把所有 class 打包成一個超大包 dex因此所有 class 的內容全部加在一起才會撞到限制至於 function name 的問題, 不論是 bytecode 或 dex都是有一個「method 列表」, 用你提到的字串表示 method實際的 bytecode / dex assembly 上還是使用列表索引class bytecode 其實某個意味上還更驚悚: 它只有一個常數池所有物件/函數/成員變數等等的參考都在常數池裡有位置不像 dex 是物件一個池, 方法一個池, 字串一個池等等這當然也跟 class 一般大小並不大有關就是
作者: ssccg (23)   2016-06-23 18:08:00
其實multidex就是改成很多個class file的方向啊後續的問題是舊版Android沒有原生支援讀取多個dex造成的
作者: HuangJC (吹笛牧童)   2016-06-23 18:21:00
所以新版完全無痛解決了嗎?畢竟公司現在只有我有4.3如果說維護成本太高,5.0以上市佔又高,我們可能直接捨棄那些維護的 code;交給 compiler 就好了..
作者: ssccg (23)   2016-06-23 18:26:00
5.0以後其實是換了一套VM(ART),會在安裝時先把所有dex再compile成另一格式的執行檔oat,VM和檔案格式都換了自然可以修掉當初設計Dalvik指令集的錯誤了..AS可以寫Java,新增module選Java Library,然後在Run >Edit Configurations自己新增一個Application類型的設好Main class就能跑了,console就是Run那個視窗bytecode java最簡單就用JDK的javapdex用android SDK的dx --dump或dexdump
作者: swallowcc (guest)   2016-06-23 22:59:00
mac可以裝多重版本jdk, 然後用command line切換版本

Links booklink

Contact Us: admin [ a t ] ucptt.com