2015-11-26 41 views
5

我基本上理解了託管代碼和本地代碼以及它們的difference的想法。但是他們在技術上可以相互溝通?想象下面的例子:混合代碼(native,managed):它是如何(技術上)互操作的?

我得到了一些靜態或動態的C++庫,它是爲特定平臺編譯的。現在我編寫一個Java程序。在這段代碼中,我使用「native」關鍵字調用庫函數。我使用字節碼構建了一個jar文件,並且C++庫文件將保持獨立。結果將不再是平臺無關的。

  1. 但是,java程序如何知道被調用的本地方法是否存在?

  2. 整個程序代碼在運行時如何執行?我知道字節碼將被解釋或編譯與JIT。

  3. 這一切如何適合沙盒模式?本機代碼是否也在沙盒中執行?

  4. 它是否工作,因爲(java和C++)代碼最終都是機器代碼?

也許這是一個愚蠢的問題。但我總是想知道...

編輯:我有3個很好的答案。真的不能決定哪一個對我最有幫助。但我會將這個問題標記爲答案,以便從我身邊關閉這個話題。

回答

2
  1. 直到你調用該方法後才知道。本機代碼駐留在.DLL或.so中; java運行時會查找與您創建的本機方法相對應的特定入口點(如果您使用的是JNI,則有一個工具可以解析這些方法並創建函數存根,在編譯時會導致這些入口點)。如果想要的入口點不在那裏,則會拋出異常。

  2. 由JIT生成的代碼並不完全是自足的;它不時需要調用外部本地代碼(包括低級運行時例程或OS服務)。使用相同的機制來調用您的本地方法的代碼。

  3. 不可以。你可以在那裏做一些純粹的C/C++程序。唯一可以阻止它受到損害的是外部安全措施(登錄權限限制,其他操作系統保護,安全軟件等),但虛擬機不會保護您。

  4. 不,JNI在JIT出現之前就存在。機制是一樣的,如果字節碼由解釋器運行,並且你希望這個解釋器調用本地代碼,你只需要一些邏輯來確定給定的方法是「外部的」並且應該被稱爲本地代碼。該信息包含在編譯後的.class文件中,當解釋器或JIT加載它時,它會創建一個內存表示形式,使得在調用方法時很容易引導該調用。

1

這取決於平臺。在Linux,Solaris等上,JRE使用dlopen。在Windows上,它使用LoadLibraryExGetProcAddress。如果JRE在解釋模式下運行,它將調用該函數;在編譯模式下,它將Java字節碼編譯爲調用該函數的本地代碼。

在我熟悉的所有JRE上,您無法直接在靜態庫中調用本機函數;只有一個在動態庫中。

原生代碼不必侷限於單個平臺;如果它是標準C語言,那麼可以使用交叉編譯器爲每個可用JRE的平臺編譯它。