2014-08-27 31 views
1

我有一個JNI庫,我已經寫入它來捕獲傳感器(主要是加速計和陀螺儀)數據,並對所述數據執行一些特徵檢測算法。檢測到的功能可通過幾個配置文件進行配置。當檢測到功能時,JNI使用回調通知應用程序的java端。所有這些都很好。實例化來自Java的JNI庫的多個副本

現在我希望能夠同時運行同一個JNI庫的多個實例(這樣我就可以同時識別多個配置文件中的功能)。爲此,我編寫了一個'包裝器'類,它實現了JNI庫的回調,並負責庫的所有初始化。我打算簡單地實例化這個類並分別使用每個實例。我發現,雖然每個包裝器實例是不同的,但是該庫在各個實例之間重複使用,就像它是靜態聲明的一樣。當我嘗試從Wrapper類的第二個實例初始化庫時,我發現它已經被初始化。

這裏是相似的代碼的包裝類,我寫:

public class JNIWrapper { 

    public native int initializeJNI(String configPath); 
    public native void endProcessing(); 
    public native int getInstanceIdFromJNI(); 

    public JNIWrapper(){ 
     try { 
      System.loadLibrary("libjnicode.so"); 
     } 
     catch (Exception e) { 
      Log.e("JNI", "WARNING: Could not load libjnicode.so: " + e.getMessage()); 
     } 
    } 

    public int initialize(String configPath){ 
     return initializeJNI(configPath); 
    } 
    public void stop(){ 
     endProcessing(); 
    } 
    public void callbackFromJNI(int output, int instanceId){ 
     //notify the subscribed application(s) of the feature detection 
     //via message passing. 
    } 
} 

有誰知道我可以實例化一個JNI庫的多個副本?
謝謝!

回答

4

你不能那樣做。動態鏈接器只會將給定的.so文件加載到一個進程中。

理想情況下,您可以修改庫,使其具有輕量的面向對象風格,允許您從配置文件或調用中創建實例並初始化這些實例(而不是進程級靜態)。這並不像看起來那麼複雜 - 基本上把你所有的狀態放在一個結構中,並通過所有的調用傳遞指針。你會有一個馬拉松編輯會話,導致一個疲憊的「粘貼」手指,然後一些錯誤清理。幸運的是,一旦你刪除了靜態變量,你將在剩下的所有嘗試中都會遇到編譯錯誤。

一個非常冒險的替代方案可能是在你的AndroidManifest.xml中聲明一些遠程過程服務並將這個庫加載到其中的每一箇中。或者,真的打破了Android模型(並且存在隨機查殺的理論風險),將庫加載到多個按需創建的本機可執行文件中。

+1

並注意這是操作系統的屬性,而不是Java。 – EJP 2014-08-27 20:03:38

+0

謝謝。我很害怕這種情況。我也在想我可以生成10個.so文件的副本,並在每次實例化一個新包裝時使用一個新副本。任何想法,如果這將工作? – 2014-08-27 21:33:07

+1

如果您可以通過一些大量重命名操作(objcopy?)使導出的函數和變量名唯一,但它會使您的apk放大。 – 2014-08-27 22:04:09