2017-02-07 23 views
3

В java-8 источниках мы можем найти довольно хитрый способ оптимизации JIT внутри класса Class:оптимизации JIT предотвращающие методы

/* 
* Private constructor. Only the Java Virtual Machine creates Class objects. 
* This constructor is not used and prevents the default constructor being 
* generated. 
*/ 
private Class(ClassLoader loader) { 
    // Initialize final field for classLoader. The initialization value of non-null 
    // prevents future JIT optimizations from assuming this final field is null. 
    classLoader = loader; 
} 

Таким образом, этот конструктор никогда не вызывается, но JIT будет «надули» на этот трюк.

Мой вопрос: может ли быть реализован несколько иначе, скажем

private Class() { 
    classLoader = (ClassLoader)(new Object()); 
} 

Это абсолютно бессмысленны логики, но это имеет значение, если конструктор никогда не был вызван?

Будет ли такой трюк также предотвращать JIT от этой оптимизации?

+0

Я не могу представить, что он используется в чем-то меньшем, чем собственный код, в частности потому, что он не является конструктором с безопасным типом. – Makoto

+0

Поле вашего класса 'classLoader' Вы имеете в виду? – Andremoniy

+0

Нет, я имею в виду этот частный конструктор.Я не могу использовать его в какой-либо библиотеке Java, и я сомневаюсь, что наши смертные захотят использовать его, поскольку он не является типом «класса». Помните: 'Класс' определяется как' Класс '. – Makoto

ответ

5

В Java 6 и Java 7 (и Java 8 до обновления 40) конструктор прост как private Class() {}, но в этих версиях также нет поля classLoader.

Это означает, что связь между Class и ClassLoader должны быть сохранены в специальном JVM определенным образом, таким образом, getClassLoader() должен вызывать в метод native, не обязательно с участием JNI, а скорее обрабатывается как внутренней работы виртуальной машины Java, но все еще требующих особого внимания внутри собственного кода JVM. Кроме того, сборщик мусора должен был знать о специальных отношениях.

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


Теперь, когда Class объектов создаются с помощью специального кода виртуальной машины Java, не используя заявленный конструктор, это может противоречить условиям оптимизирующего Джита, сделанные на основе анализа фактического кода конструктора предсказывать возможные значения этого final поля.

Обратите внимание, что никто не сказал, что текущий JIT - это умный. В комментарии говорится о гипотетических «будущих оптимизации JIT». Наличие конструктора, инициализирующего поле со значением параметра, соответствует тому, что фактически делает JVM.

Напротив, конструктор, подобный предложенному вами classLoader = (ClassLoader)(new Object());, может привести к гипотетическому оптимизатору, чтобы сделать вывод о том, что это поле не может быть инициализировано фактическим ClassLoader экземпляром, поскольку этот код никогда не может завершиться нормально.

+1

Похоже, что более ранние версии Java 8 также не имели поля 'classLoader'. Он [использовал собственный метод] (http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8-b132/java/lang/Class.java#Class.getClassLoader0% 28% 29). – 4castle

+1

@ 4castle: похоже, он был добавлен точно в обновление 40. – Holger

0

В комментарии к источнику Class указано, что значение инициализации делает будущую оптимизацию JIT , зная, что поле classLoader не равно нулю. Таким образом, оптимизатор может сделать еще лучшую работу в будущем.

Чтобы предотвратить оптимизацию, просто объявите свои поля volatile.