我有一个Java类,它包含一个仅由本机JNI方法使用的本机句柄指针。让我们使用这个类(在http://thebreakfastpost.com/2012/01/23/wrapping-a-c-library-with-jni-part-1/找到)作为例子:
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忽略该问题或完全禁用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
答案 1 :(得分:0)
除了禁用警告之外,我通常会尝试添加一个单元测试来检查字段的值。例如您可以检查它是非零并且对于不同的插件是不同的。
答案 2 :(得分:0)
第一种方法是使用hashCode
和equals
中的原生句柄。这适用于此本机句柄是某种主键(例如,设备句柄)的对象。它对于使用其他数据来识别对象更有意义的对象不起作用(例如,用户对象可能已经有用户ID)。
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代码,使用本机指针直接使用本机C API访问对象而不是使用Java API,它甚至可能很有用:
public final Device
{
/** The device handle. Set by native code. */
private long handle;
public long getHandle()
{
return this.handle;
}
}