2011-05-20 90 views
4

一個Java類做類似下面的JNI可以在初始化時調用對象的方法嗎?

public class Foo { 

    private final NativeCallbackHandler handler; 

    public Foo(NativeCallbackHandler handler) { 
     // I've shortened this for exposition, callSomeNativeMethod 
     // really happens in a superclass that I don't own (and is 
     // part of the lib that gives me the native part) 
     callSomeNativeMethod(); 
     this.handler = handler; 
    } 

    public void handleNativeCallback(Object args) { 
     this.handler.callback(args); 
    } 

    private native int callSomeNativeMethod(); 
} 

你可以假設本地方法做一些事情,可能會導致本機代碼調用handleNativeMethod

我有2個相關的問題

  1. 我相信本機代碼必須調用此對象上的句柄,並且還調用GetMethodID以訪問要調用的方法,是否可以讓該本機代碼調用方法之前對象是否完全初始化?
  2. 如果可以,未初始化的最終字段的語義是什麼?

如果1是肯定的話,我預計2到訪問炸燬它,所以我想我們需要使它成爲AtomicReference爲了安全地訪問它沒有吹起來。

注意我無法控制本機庫的行爲。

+1

是否有一些原因爲什麼你在處理程序字段設置之前調用'callNativeMethod'? – Andrew 2011-05-20 17:57:23

+0

難道你不能建立這個並運行它並找出?你好像已經有90%的存在了...... – 2011-05-20 18:00:28

+0

因爲我沒有擁有本地庫中的代碼,這就是它的行爲方式。問題是它不太可能會調用這個方法(這是一個時間問題),我不能*做*它做到這一點。它取決於網絡中發生的各種事情,以及某些消息何時到達,以何種順序進行,這意味着很難確定性地重新創建。因此,我需要知道在理論上我是否有問題,如果是這樣,問題是什麼 – Matt 2011-05-20 18:00:34

回答

3

看起來像是可能的。本機代碼不會強制實施限制。

http://java.sun.com/docs/books/jni/html/pitfalls.html#36197

10.9違反訪問控制規則

的JNI不會強制執行類,字段, 和方法的訪問控制,可以在Java的 編程語言水平通過表達限制 使用修飾符如private和 final。可以編寫本機 代碼來訪問或修改對象的字段,即使在編程語言級別爲 時 會導致IllegalAccessException。 JNI的寬容是一個有意識的 設計決定,因爲本地 代碼可以訪問和修改堆中的任何內存 位置。

跳過的原生代碼 源語言級別的訪問檢查 可能會對 程序執行產生不良影響。例如,如果在即時(JIT)編譯器 已內聯訪問該字段後,本地方法修改最終字段 ,則可能會創建不一致性 。 同樣,本地方法不應該 在 java.lang.String或java.lang.Integer的實例中修改不可變對象,例如 字段。 這樣做可能會導致 不變量在Java平臺 實現中的破壞。

當您訪問未初始化的最終引用時,這並未定義行爲,但我們可以做出相當好的猜測。

就個人而言,我會盡量避免這個問題,無論是通過:

  • 確保一切都回調
  • 在回調過程中無所作爲,直到一個標誌設置在初始化完成之前初始化。
2

從超類的構造函數handleNativeCallback呼叫將導致NullPointerException,因爲設置處理程序之前被調用。這個調用是由JNI還是由純Java代碼完成的。

+0

+1好點 - 並且它是否是最終的。以下是純Java示例:http://ideone.com/0HoFk。 – 2011-05-20 21:53:37

相關問題