может ли компилятор присвоить значение переменной даже до того, как переменная будет фактически инициирована? - PullRequest
3 голосов
/ 10 мая 2011

Я только что прочитал http://www.javaworld.com/javaworld/jw-04-2003/jw-0425-designpatterns.html?page=5 и там написано:

компилятор может присвоить значение переменной-члену singleton до того, как конструктор синглтона называется

Мне интересно, если это опечатка. Действительно ли они действительно хотели сказать: реализация JVM бесплатна для вместо , компилятор свободен для .

и мой второй вопрос: у нас тоже есть эта проблема с C # / VB? (в котором «компилятор» может присваивать значение переменной даже до того, как переменная будет полностью инициирована / даже до полного запуска функции-конструктора класса переменной.

Ответы [ 2 ]

4 голосов
/ 10 мая 2011

В Java выделение памяти для объекта и вызов конструктора - это две отдельные операции.Например, что-то вроде

Object o = new Object();

компилируется в следующие байт-коды:

0:  new #2; //class java/lang/Object
3:  dup
4:  invokespecial   #1; //Method java/lang/Object."<init>":()V
7:  astore_1

После инструкции 0 ссылка на выделенный, но неструктурированный объект находится в стеке.Конструктор не вызывается до смещения 4. Определенно, ничто не мешает компилятору присвоить эту ссылку любой переменной, в которой он хочет, включая статический член.Таким образом, статья верна.

Я не знаю байт-код CLR, но я думаю, что он довольно близко подходит к набору инструкций JVM, и я предполагаю, что для этого существует такой же нюанс, связанный с потокамивремя выполнения также.Это конечно верно для компиляторов нативного кода.

1 голос
/ 10 мая 2011

Ответ на первую часть вопроса заключается в том, что вы правы, хотя это скорее случай небрежной терминологии, чем опечатка или ошибка. (Проще говоря, компилятор не присваивает значения переменным ... это происходит только при выполнении кода, сгенерированного компилятором.)

Более технически точный пересчет будет:

"... потому что компилятор может генерировать код, который может привести к записи значения в память для переменной-члена singleton до вызова конструктора singleton, и созданный объект был вспыхнул в памяти. "

Подобные вещи чаще всего случаются на уровне компилятора собственного кода, когда компилятор (юридически) переупорядочивает инструкции или просто в результате конвейерной обработки памяти. Модель памяти Java специально позволяет это, так что компилятор может генерировать код, который работает быстрее на многоядерных машинах. (С другой стороны, ваш многопоточный код должен синхронизироваться требуемым образом, иначе он может быть ненадежным.)

(Теоретически, для компилятора байт-кода также возможно переупорядочить байт-коды, но есть вероятность, что он этого не сделает. В компиляторе байт-кода мало что дает для детальной оптимизации. Действительно, это может быть вредно, поскольку потенциально усложняет работу оптимизатора JIT-компилятора.)


Я оставлю дела на C # и VB кому-то, кто знаком со спецификациями этих языков.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...