java类的功能类似于以下
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个相关问题
GetMethodID
来访问要调用的方法,该本机代码是否可以在>之前调用 strong>对象是否已完全初始化?如果1为是,那么我希望2能够在访问它时爆炸,因此我想我们需要将其设为AtomicReference
才能安全地访问它而不会爆炸。
注意我无法控制本机库的行为。
答案 0 :(得分:3)
看起来有可能。本机代码不会强制执行final
限制。
来自http://java.sun.com/docs/books/jni/html/pitfalls.html#36197:
10.9违反访问控制规则
JNI不强制执行class,field, 和方法访问控制限制 可以在Java上表达 编程语言水平通过 使用修饰符如private和 最后。可以写原生的 用于访问或修改字段的代码 即使这样做也是对象 Java编程语言水平会 导致IllegalAccessException。 JNI的放纵是有意识的 设计决定,鉴于原生 代码可以访问和修改任何内存 无论如何,在堆中的位置。
绕过的本机代码 源语言级访问检查 可能会产生不良影响 程序执行。例如,一个 如果a,可能会产生不一致 native方法修改final字段 在即时(JIT)编译器之后 已经内联访问该字段。 同样,本机方法不应该 修改不可变对象,如 实例中的字段 java.lang.String或java.lang.Integer。 这样做可能会导致破损 Java平台中的不变量 实施
当您访问未初始化的最终引用时,这不会定义行为,但我们可能会做出相当不错的猜测。
就个人而言,我会尝试通过以下方式避免这个问题:
答案 1 :(得分:2)
从超类构造函数调用handleNativeCallback
将导致NullPointerException
,因为它在设置处理程序之前被调用。调用是由JNI还是纯Java代码没有区别。