天天看點

《Java 本地接口規範》- 調用 API調用 API 概述 初始化結構 調用 API 函數

調用 api 允許軟體廠商将 java 虛拟機加載到任意的本地程式中。廠商可以傳遞支援 java 的應用程式,而不必連結 java 虛拟機源代碼。

本章首先概述了調用 api。然後是所有調用 api 函數的引用頁。

若要增強 java 虛拟機的嵌入性,可以用幾種方式來擴充 jdk 1.1.2 中的調用 api。

以下代碼示例說明了如何使用調用 api 中的函數。在本例中,c++ 代碼建立 java 虛拟機并且調用名為 <code>main.test</code> 的靜态方法。為清楚起見,我們略去了錯誤檢查。

本例使用了 api 中的三個函數。調用 api 允許本地應用程式用 jni 接口指針來通路虛拟機特性。其設計類似于 netscape 的 jri 嵌入式接口。

jni_createjavavm() 函數加載并初始化java 虛拟機,然後将指針傳回到 jni 接口指針。調用 <code>jni_createjavavm()</code> 的線程被看作主線程。

jni 接口指針 (<code>jnienv</code>) 僅在目前線程中有效。如果另一個線程需要通路 java 虛拟機,則該線程首先必須調用<code>attachcurrentthread()</code> 以将自身連接配接到虛拟機并且獲得 jni 接口指針。連接配接到虛拟機之後,本地線程的工作方式就與在本地方法内運作的普通 java 線程一樣了。本地線程保持與虛拟機的連接配接,直到調用

<code>detachcurrentthread()</code> 時才斷開連接配接。

主線程不能自己斷開與虛拟機的連接配接。而是必須調用<code>destroyjavavm()</code> 來解除安裝整個虛拟機。

虛拟機等到主線程成為唯一的使用者線程時才真正地解除安裝。使用者線程包括 java 線程和附加的本地線程。之是以存在這種限制是因為 java 線程或附加的本地線程可能正占用着系統資源,例如鎖,視窗等。虛拟機不能自動釋放這些資源。解除安裝虛拟機時,通過将主線程限制為唯一的運作線程,使釋放任意線程所占用系統資源的負擔落到程式員身上。

不同的 java 虛拟機實作可能會需要不同的初始化參數。很難提出适合于所有現有和将來的 java 虛拟機的标準初始化結構。作為一種折衷方式,我們保留了第一個域 (<code>version</code>) 來識别初始化結構的内容。嵌入到 jdk 1.1.2 中的本地應用程式必須将版本域設定為

<code>0x00010001</code>。盡管其它實作可能會忽略某些由 jdk 所支援的初始化參數,我們仍然鼓勵虛拟機實作使用與 jdk 一樣的初始化結構。

<code>0x80000000</code> 到 <code>0xffffffff</code> 之間的版本号需保留,并且不為任何虛拟機實作所識别。

以下代碼顯示了初始化 jdk 1.1.2 中的 java 虛拟機所用的結構。

在 jdk 1.1.2 中,初始化結構提供了鈎子,這樣在虛拟機終止時,本地應用程式可以重定向虛拟機消息并獲得控制權。

當本地線程與jdk 1.1.2 中的 java 虛拟機連接配接時,以下結構将作為參數進行傳遞。實際上,本地線程與 jdk 1.1.2 連接配接時不需要任何參數。<code>jdk1_1attachargs</code> 結構僅由 c 編譯器的填充槽組成,而 c 編譯器不允許空結構。

javavm 類型是指向調用 api 函數表的指針。以下代碼示例顯示了這種函數表。

注意,<code>jni_getdefaultjavavminitargs()</code>、jni_getcreatedjavavms() 和<code>jni_createjavavm()</code>這三個調用 api 函數不是 javavm 函數表的一部分。不必先有

<code>javavm</code> 結構,就可以使用這些函數。

jintjni_getdefaultjavavminitargs(void *vm_args);

傳回 java 虛拟機的預設配置。在調用該函數之前,平台相關代碼必須将 <code>vm_args-&gt;version</code> 域設定為它所期望虛拟機支援的 jni 版本。在 jdk 1.1.2 中,必須将

<code>vm_args-&gt;version</code> 設定為 <code>0x00010001</code>。(jdk1.1 不要求平台相關代碼設定版本域。為了向後相容性,如果沒有設定版本域,則 jdk 1.1.2 假定所請求的版本為 0x00010001。jdk 的未來版本将要求把版本域設定為适當的值。) 該函數傳回後,将把<code>vm_args-&gt;version</code> 設定為虛拟機支援的實際 jni 版本。

vm_args:指向 <code>vm-specific initialization</code>(特定于虛拟機的初始化)結構的指針,預設參數填入該結構。

如果所請求的版本得到支援,則傳回“0”;如果所請求的版本未得到支援,則傳回負數。

jintjni_getcreatedjavavms(javavm **vmbuf, jsize buflen,

jsize *nvms);

傳回所有已建立的java 虛拟機。将指向虛拟機的指針依據其建立順序寫入 vmbuf 緩沖區。最多寫入 buflen 項。在 *nvms 中傳回所建立虛拟機的總數。

jdk 1.1 不支援在單個程序中建立多個虛拟機。

vmbuf:指向将放置虛拟機結構的緩沖區的指針。

<code>buflen</code>:緩沖區的長度。

<code>nvms</code>:指向整數的指針。

成功時傳回“0”;失敗則傳回負數。

jintjni_createjavavm(javavm **p_vm, jnienv **p_env,

void *vm_args);

加載并初始化java 虛拟機。目前線程成為主線程。将<code>env</code> 參數設定為主線程的 jni 接口指針。

jdk 1.1.2 不支援在單個程序中建立多個虛拟機。必須将 vm_args 中的版本域設定為 <code>0x00010001</code>。

p_vm:指向位置(其中放置所得到的虛拟機結構)的指針。

<code>p_env</code>:指向位置(其中放置主線程的 jni 接口指針)的指針。

<code>vm_args</code>: java 虛拟機初始化參數。

jintdestroyjavavm(javavm *vm);

解除安裝 java 虛拟機并回收資源。隻有主線程能夠解除安裝虛拟機。調用 <code>destroyjavavm()</code> 時,主線程必須是唯一的剩餘使用者線程。

vm:将銷毀的 java 虛拟機。

jdk 1.1.2 不支援解除安裝虛拟機。

jintattachcurrentthread(javavm *vm, jnienv **p_env,

void *thr_args);

将目前線程連接配接到 java 虛拟機。在 <code>jnienv</code> 參數中傳回 jni 接口指針。

試圖連接配接已經連接配接的線程将不執行任何操作。

本地線程不能同時連接配接到兩個 java 虛拟機上。

vm:目前線程所要連接配接到的虛拟機。

<code>p_env</code>:指向位置(其中放置目前線程的 jni 接口指針)的指針。

<code>thr_args</code>:特定于虛拟機的線程連接配接參數。

jintdetachcurrentthread(javavm *vm);

斷開目前線程與 java 虛拟機之間的連接配接。釋放該線程占用的所有 java 監視程式。通知所有等待該線程終止的 java 線程。

主線程(即建立 java 虛拟機的線程)不能斷開與虛拟機之間的連接配接。作為替代,主線程必須調用 <code>jni_destroyjavavm()</code> 來解除安裝整個虛拟機。

vm:目前線程将斷開連接配接的虛拟機。