1

我有一个 Java 类,它包含一个仅由本机 JNI 方法使用的本机句柄指针。让我们以这个类(位于http://thebreakfastpost.com/2012/01/23/wrapping-ac-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 代码可以访问该字段。

将字段设置为受保护或公共也是一个坏主意,因为这样可以从外部(直接或通过扩展类)修改句柄,这会导致崩溃。Package-private 并没有那么糟糕,但是像 checkstyle 这样的源代码分析器的默认设置抱怨编程风格不好。

当然,我可以添加@SuppressWarnings("unused")注释以使 eclipse 警告静音,或者我可以添加一些注释,以便 checkstyle 忽略该问题或完全禁用 checkstyle 中的检查。但我不确定是否需要这样做,或者我是否只是做错了。

那么,对于使用 JNI 代码的类中的本地句柄的可见性,是否有一些最佳实践?或者也许可以在 Java 代码中完全避免它们?

4

3 回答 3

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 是个好主意

于 2013-04-12T11:11:32.580 回答
0

除了禁用警告之外,我通常会尝试添加一个单元测试来检查字段的值。例如,您可以检查它是否非零并且对于不同的插件是不同的。

于 2013-04-12T11:08:18.467 回答
0

嗯...也许我找到了替代方案。好吧,实际上有两种选择。两者都只是将私有值用于实际目的,因此代码分析器没有理由抱怨未使用的代码。

第一种选择是在hashCodeand中使用本机句柄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;
    }    
}

第二种选择是简单地为本机句柄提供一个吸气剂。退回它是无害的,因为它仍然无法从外部修改。如果有人想编写自定义 JNI 代码,使用本机指针直接使用本机 C API 而不是使用 Java API 访问对象,它甚至可能很有用:

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

    public long getHandle()
    {
        return this.handle;
    }
}
于 2013-04-12T12:01:41.780 回答