multidex 討論

看板java作者 (吹笛牧童)時間7年前 (2016/06/23 12:44), 7年前編輯推噓2(2026)
留言28則, 4人參與, 最新討論串1/1
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 的問題一樣了) -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 60.251.197.55 ※ 文章網址: https://www.ptt.cc/bbs/java/M.1466657081.A.8C2.html ※ 編輯: HuangJC (60.251.197.55), 06/23/2016 12:47:53

06/23 13:45, , 1F
64K 是 dex 的指令集設計上的問題
06/23 13:45, 1F

06/23 13:46, , 2F
其實 java 的 bytecode 本來也是有這限制的
06/23 13:46, 2F

06/23 13:46, , 3F
invokevirtual 後面跟的數字也是最大 64K
06/23 13:46, 3F

06/23 13:47, , 4F
但 java class 的函數計數只限於單一 class
06/23 13:47, 4F

06/23 13:47, , 5F
所以除非是超巨型 class 不然應該不會碰到
06/23 13:47, 5F
這合理多了, 畢竟 class 裡 function 很多,但對內很多,對外則隱藏細節 宣告為 private 的外部根本沒必要見到 (我都有盡量封起來) 既然寫 class 的精神就是儘量隱藏細節,就不應該全部 class 編一份表格 這樣這份表格等於曝露了所有 api 接口,根本就沒有 private 的感覺 全都 public 了... 所以說是 java 的限制,這不知是我看錯還是那幾份文件寫錯

06/23 13:47, , 6F
但 dex 是把所有 class 打包成一個超大包 dex
06/23 13:47, 6F
那我就不知它有什麼問題非得這麼做了 它大可改回來,而不是叫我們學 multidex

06/23 13:48, , 7F
因此所有 class 的內容全部加在一起才會撞到限制
06/23 13:48, 7F

06/23 13:48, , 8F
至於 function name 的問題, 不論是 bytecode 或 dex
06/23 13:48, 8F

06/23 13:49, , 9F
都是有一個「method 列表」, 用你提到的字串表示 method
06/23 13:49, 9F

06/23 13:50, , 10F
實際的 bytecode / dex assembly 上還是使用列表索引
06/23 13:50, 10F

06/23 13:51, , 11F
class bytecode 其實某個意味上還更驚悚: 它只有一個常數池
06/23 13:51, 11F

06/23 13:51, , 12F
所有物件/函數/成員變數等等的參考都在常數池裡有位置
06/23 13:51, 12F

06/23 13:52, , 13F
不像 dex 是物件一個池, 方法一個池, 字串一個池等等
06/23 13:52, 13F

06/23 13:52, , 14F
這當然也跟 class 一般大小並不大有關就是
06/23 13:52, 14F

06/23 18:08, , 15F
其實multidex就是改成很多個class file的方向啊
06/23 18:08, 15F

06/23 18:10, , 16F
後續的問題是舊版Android沒有原生支援讀取多個dex造成的
06/23 18:10, 16F

06/23 18:21, , 17F
所以新版完全無痛解決了嗎?畢竟公司現在只有我有4.3
06/23 18:21, 17F

06/23 18:21, , 18F
如果說維護成本太高,5.0以上市佔又高,我們可能直接捨棄
06/23 18:21, 18F

06/23 18:21, , 19F
那些維護的 code;交給 compiler 就好了..
06/23 18:21, 19F

06/23 18:26, , 20F
5.0以後其實是換了一套VM(ART),會在安裝時先把所有dex再
06/23 18:26, 20F

06/23 18:28, , 21F
compile成另一格式的執行檔oat,VM和檔案格式都換了自然可
06/23 18:28, 21F

06/23 18:29, , 22F
以修掉當初設計Dalvik指令集的錯誤了..
06/23 18:29, 22F
剛打的,刪掉一大段 想寫個小程式驗,卻寫好久 順便問兩個問題: 1.AS 可以寫純 Java 程式嗎? (其實我想要這個,因為我要實驗 Java 語法,沒必要 upload 至手機,那太慢) 看來不行 2.Eclipse 可以,但我不想裝 Java 1.6 (我是用 Mac),請問怎麼做? 我有裝最新的 Java 1.8 了.. 同事叫我只留一套,因為自從 Build Machine build 的才會 endless loop 後 他說大家要統一 (要死一起死的意思,才能對質 XD;但我的 build 不會 endless loop 耶) 嗯,還是前面問的:那我要怎麼看 bytecode? 看來要對質,還是要對到這境界才行.. ※ 編輯: HuangJC (60.251.197.55), 06/23/2016 18:36:45

06/23 18:42, , 23F
AS可以寫Java,新增module選Java Library,然後在Run >
06/23 18:42, 23F

06/23 18:43, , 24F
Edit Configurations自己新增一個Application類型的
06/23 18:43, 24F

06/23 18:44, , 25F
設好Main class就能跑了,console就是Run那個視窗
06/23 18:44, 25F

06/23 18:50, , 26F
bytecode java最簡單就用JDK的javap
06/23 18:50, 26F

06/23 18:52, , 27F
dex用android SDK的dx --dump或dexdump
06/23 18:52, 27F

06/23 22:59, , 28F
mac可以裝多重版本jdk, 然後用command line切換版本
06/23 22:59, 28F
文章代碼(AID): #1NQsavZ2 (java)