我想知道,jvm 旨在將位元組碼轉換為機器碼,但我似乎找不到任何關于逆操作是否可能的資訊。似乎如果有可能它會更頻繁地發生,因為它允許您在 jvm 運行的任何地方運行任何二進制檔案。
所以,顯然,我在這里缺少一些東西,但我不確定是什么。當然,有些應用程式會依賴于系統相關的框架,但是對于僅依賴于例如 c 標準庫的簡單應用程式,似乎應該是可能的?有人知道為什么不嘗試這種事情嗎?
uj5u.com熱心網友回復:
將任意機器碼二進制轉換為 JVM 位元組碼是不切實際的。例如,C 程式和庫中的指令在 JVM 位元組碼中沒有等效的指令。您必須從二進制程式中判斷程式的含義,并將該意圖轉化為某種東西。在任意機器代碼程式的一般情況下,我們不知道如何自動執行此操作。
然而,你可以做的是用 Java 撰寫一個機器代碼模擬器,它可以解釋所有可能的指令集和作業系統的機器代碼程式和系統呼叫——然后你可以獲取任何程式二進制檔案并使用 JVM 模擬它!我們知道如何做到這一點:這是一個簡單的編程問題。
這將耗費大量精力(可能需要數十萬工時),并且具有明顯的性能下降缺點:我們希望程式以非常、非常小的、極小的部分運行它們的原生執行性能。它還會冒許多錯誤的風險并需要進行廣泛的測驗,因此,簡而言之,這是一個大專案。
uj5u.com熱心網友回復:
您的問題很有趣,因為人們通常會問相反的問題,“可以將 Java(位元組碼)程式編譯為本機可執行檔案”,認為 Java 太慢了。如今,Java (VM) 并不慢,與精心優化的本機程式可能需要的相比,它只是消耗更多的記憶體和功率,而且速度有點慢。
您還詢問了一個特定案例 - 僅依賴于 C 標準庫的簡單應用程式。我想了想,讓我解釋一下將此類程式轉換為 JVM 位元組碼可能涉及哪些問題。
我的第一個編程是Java,但我從來沒有認真處理過JVM,所以有些細節可能是錯誤的。
您必須實作標準 C 庫 (libC)。如果您可以依賴 Java 標準庫,這相對容易,它的覆寫范圍比 libC 更廣泛。如果沒有 Java 依賴項,您將不得不為每個平臺實作本機方法,因為 JVM 不提供任何內置函式來與用戶互動,例如控制臺 IO。
現在,您必須檢測 libC 呼叫或任何函式呼叫的引數存盤在何處。根據 ABI,它將位于暫存器或特定記憶體區域中。通常,它就像 一樣簡單r0 = 1; r1 = 2; call f(r0, r1),但有時 的值r0可以在代碼中的某個地方確定。您需要一種機制來找出r0在呼叫之前最終修改的時間。
該程式永遠不會對 libC 進行一系列呼叫。它將具有應為 JVM 翻譯的各種操作。商業用途的現代 CPU 是注冊機,但 JVM 是堆疊機,或者實際上是混合機。
基本的算術運算是在堆疊上完成的,但方法呼叫會創建自己的frame。每個幀都有一個區域變數陣列,其大小在編譯時確定,類似于本機方法有自己的堆疊幀。例如,當您呼叫int add(int a, int b)此方法時,該方法將具有一個包含至少包含兩個引數的區域變數陣列的框架。然后,這些變數將通過load指令推入堆疊。一條add指令將消耗堆疊頂部的兩個變數并用結果替換它們。您必須將典型暫存器機器的指令序列轉換為這種混合機器 JVM 位元組碼。
總之,我認為花費大量時間和精力是可行的,但請注意,這是關于僅依賴于 libC 的簡單應用程式的簡單案例。我不確定這樣的專案是否值得人力投資,但在此程序中可能會發現一些有趣的發現。
我有一個假設,一個只依賴于 libC 的程式可能是從 C 程式編譯的。如果不是這種情況,則可能沒有通用的解決方案。有可能撰寫故意混淆的匯編代碼以使反編譯器失敗。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/498476.html
