2013-04-12 27 views
1

我有一個Java類,它包含一個本地句柄指針,它只被本地JNI方法使用。讓我們使用這個類(在http://thebreakfastpost.com/2012/01/23/wrapping-a-c-library-with-jni-part-1/找到)爲例:爲JNI控制的字段選擇哪種可見性?

public class Plugin 
{ 
    private long nativeHandle; 

    protected Plugin(long handle) { 
     nativeHandle = handle; 
    } 

    public native String getIdentifier(); 
    public native String getName(); 
    public native String getDescription(); 
    public native int getPluginVersion(); 

}

所以在這個例子中,手柄是私有的。 JNI不關心可見性。但是像Eclipse這樣的源代碼分析器抱怨這個領域,因爲它沒有被使用。 Eclipse不知道有一些JNI代碼訪問這個字段。

將該字段設置爲protected或public也是一個糟糕的主意,因爲然後該句柄可以從外部(直接或通過擴展類)進行修改,從而導致崩潰。 Package-private並不是那麼糟糕,但像checkstyle這樣的源代碼分析器的默認設置會抱怨糟糕的編程風格。

當然,我可以添加一個@SuppressWarnings("unused")註釋來消除日食警告,或者我可以添加一些註釋,以便checkstyle完全忽略問題或禁用check in checkstyle。但我不確定這是否需要,或者我是否做錯了。

那麼在使用JNI代碼的類中,本地句柄的可見性是否存在一些最佳實踐?或者也許他們可以以某種方式完全避免在Java代碼中?

回答

0

除了禁用警告,我通常會嘗試添加一個單元測試來檢查字段的值。例如你可以檢查它是不是零和不同的插件。

1

在java.lang.Thread中看看SRC

/** 
* Dispatch an uncaught exception to the handler. This method is 
* intended to be called only by the JVM. 
*/ 
private void dispatchUncaughtException(Throwable e) { 
    getUncaughtExceptionHandler().uncaughtException(this, e); 
} 

的Eclipse會抱怨未使用的方法,仍然是私有的,意見有助於瞭解爲什麼。

@SuppressWarnings("unused")是一個好主意IMO

0

嗯......也許我找到了一個替代方案。那麼,實際上有兩種選擇。兩者都將私有值用於實際目的,因此代碼分析器沒有理由抱怨未使用的代碼。

第一種方法是使用hashCodeequals中的本地句柄。這適用於本地句柄是某種主鍵的對象(例如設備句柄)。它不適用於使用其他數據來識別對象更有意義的對象(例如,用戶對象可能已經有用戶標識)。

public final Device 
{ 
    /** The device handle. Set by native code. */ 
    private long handle; 

    @Override 
    public int hashCode() 
    { 
     final int prime = 31; 
     int result = 1; 
     result = prime * result + (int) (this.handle^(this.handle >>> 32)); 
     return result; 
    } 

    @Override 
    public boolean equals(Object obj) 
    { 
     if (this == obj) return true; 
     if (obj == null) return false; 
     if (getClass() != obj.getClass()) return false; 
     Device other = (Device) obj; 
     if (this.pointer != other.pointer) return false; 
     return true; 
    }  
} 

第二種方法是簡單地爲本地句柄提供一個getter。返回它是無害的,因爲它仍然不能從外部修改。如果有人想編寫使用本機指針的自定義JNI代碼,而不是使用Java API直接訪問具有本機C API的對象,甚至可能會有用:

public final Device 
{ 
    /** The device handle. Set by native code. */ 
    private long handle; 

    public long getHandle() 
    { 
     return this.handle; 
    } 
}