Может ли JNI вызывать метод объекта во время инициализации? - PullRequest
4 голосов
/ 20 мая 2011

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 связанных вопроса

  1. Я считаю, что нативный код должен вызывать дескриптор этого объекта, а также вызывать GetMethodID, чтобы получить доступ к вызываемому методу. Возможно ли, чтобы этот нативный код вызывал метод до объект полностью инициализирован?
  2. Если это возможно, какова семантика неинициализированного конечного поля?

если 1 - да, тогда я ожидаю, что 2 взорвется при доступе к нему, и, следовательно, я предполагаю, что нам нужно сделать его AtomicReference, чтобы получить к нему безопасный доступ без взрыва.

Примечание. Я не контролирую поведение нативной библиотеки.

Ответы [ 2 ]

3 голосов
/ 20 мая 2011

Похоже, это возможно. Собственный код не обеспечивает ограничение final.

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

10.9 Нарушение правил контроля доступа

JNI не применяет класс, поле, и метод контроля доступа ограничения что можно выразить на Яве уровень языка программирования через использование модификаторов, таких как частные и окончательный. Можно написать родной код для доступа или изменения полей возражать, хотя делает это на Уровень языка программирования Java будет привести к IllegalAccessException. Вседозволенность JNI была сознательной дизайнерское решение, учитывая, что родной код может получить доступ и изменить любую память все равно в куче.

Собственный код, который обходит проверки доступа на уровне исходного языка может иметь нежелательные последствия для выполнение программы. Например, несоответствие может быть создано, если нативный метод изменяет конечное поле после JIT-компилятора имеет встроенный доступ к полю. Аналогично, нативные методы не должны изменить неизменяемые объекты, такие как поля в случаях java.lang.String или java.lang.Integer. Это может привести к поломке инварианты в платформе Java осуществление.

Это не определяет поведение при доступе к неинициализированной окончательной ссылке, но мы, вероятно, можем сделать довольно хорошее предположение.

Лично я бы попытался избежать этой проблемы либо:

  • Убедиться, что все было инициализировано перед обратным вызовом
  • Ничего не делать во время обратного вызова, пока не будет установлен флаг, что инициализация завершена.
2 голосов
/ 21 мая 2011

Вызов handleNativeCallback из конструктора суперкласса приведет к NullPointerException, потому что он вызывается до установки обработчика.Нет никакой разницы, был ли вызов сделан JNI или чистым кодом Java.

...