Это никак нельзя назвать созданием инстанса java.lang.Class. Вы аллоцировали обычный java.lang.Object, и испортили весь лейаут хипа, перезаписав в нём поле klass. Чтобы это было хоть чуточку похоже на правильный инстанс, надо было выделить объект нужного размера. Меньше нельзя, потому что иначе при доступе к полям своего объекта перезапишите соседнюю память. Но и больше тоже нельзя, потому что при итерировании по хипу JVM использует поле klass, чтобы узнать размер объекта и найти, где начинается следующий.
И в JPoint докладе эту проблему разбираем. Хотя видео пока только участникам конференции доступно. Но я про особенности профилирования упоминал и в прошлом докладе про стектрейсы (с 57:46).
Указал автору оригинальной статьи на ошибку, которую он, к чести, оперативно исправил. Выводы в статье поменялись. Неплохо бы теперь и перевод обновить, чтоб соответствовал новой редакции.
Если по-простому, код, который часто исполняется, и есть «горячий» по определению. В действительности, у JVM есть нетривиальная логика определения горячих методов. Опцией -XX:+PrintCompilation можно проверять, какие методы компилируются, а какие нет, но на практике это редко когда требуется.
Кстати говоря, на предстоящем JPoint будем с коллегой подробно рассказывать как раз про методики семлирования, и к этому событию приурочу кое-какие интересные обновления в async-profiler… Следите за новостями :)
Так исторически сложилось + объективная причина, что на 32-разрядных архитектурах работа с long быстрее и экономнее. Во времена JDK 1.x 64-разрядных систем ещё не было.
А вы не рассматривали вариант при таких объёмах сделать полный coredump процесса, а потом анализировать его с помощью Serviceability Agent, где уже есть всё необходимое API для вытаскивания классов, тредов, обхода хипа и т. д.?
С другой стороны, процессоры тоже давно умеют оптимизировать умножение на аппаратном уровне. Таким образом, strength reduction умножения потеряла первоначальную ценность и теперь, скорее, вредит:
Хотя в исходниках до сих пор можно встретить подобную ручную «оптимизацию», например, в IdentityHashMap.
Нет, вычислять hashCode лениво вообще не проблема. Вся история о том, где это значение хранить. И в этом смысле инициализация hashCode при создании объекта ничем не поможет.
Всё верно. Алгоритм String.hashCode прописан в спецификации Java SE API, и другие реализации Java SE не вправе его менять. А то, во что switch превращается — отдаётся на откуп компилятору. И javac генерирует код, который на любой Java SE-совместимой реализации будет корректен.
Сорри, позволил себе лёгкий троллинг :) Просто зачем автор полез в такие глубины, не разобравшись в более простых вещах? Это ставит под сомнение и всю статью.
I have found no HotSpot flag that allows changing the default generator, so experimenting with other options might need to compile from source.
Как же так? Про -XX:hashCode=N уже миллион раз писали в блогах, твиттере, на Stack Overflow и пр.
even if there is a single thread interested in the lock, the header word will be contended and require atomic operations to be handled correctly. Which defeats the whole point of biased locking.
Объяснение про несовместимость Biased Lock с identityHashCode вообще жуткое: какие-то диаграммы состояний, перемещение заголовков, бла-бла-бла… Истинная же причина проста: в целях экономии места в заголовок помещается либо признак Biased-блокировки, либо identityHashCode. Только и всего.
Ирония в том, что в конечном итоге это изменение было сделано нечаянно. Заветная строчка попала в репозиторий по ошибке вместе с коммитом к совсем другой фиче :)
MethodHandle.invoke, хоть и реализован по-другому, но делает примерно всё то же, что и Method.invoke, за исключением проверок доступа. Поэтому большого выигрыша сами по себе MethodHandles не дают. Чтобы получить максимальную выгоду от java.lang.invoke, имеет смысл MethodHandle преобразовать в экземпляр интерфейса с помощью LambdaMetafactory. И тогда вызов будет столь же быстрым, как и обычный invokeinterface.
И в JPoint докладе эту проблему разбираем. Хотя видео пока только участникам конференции доступно. Но я про особенности профилирования упоминал и в прошлом докладе про стектрейсы (с 57:46).
Подсказка: в вызове
Arrays.copyOf
надо заменитьsize
наoriginal.length
.-XX:+PrintCompilation
можно проверять, какие методы компилируются, а какие нет, но на практике это редко когда требуется.https://github.com/apangin/async-profiler
Кстати говоря, на предстоящем JPoint будем с коллегой подробно рассказывать как раз про методики семлирования, и к этому событию приурочу кое-какие интересные обновления в async-profiler… Следите за новостями :)
См. http://stackoverflow.com/questions/4166195/why-objecthashcode-returns-int-instead-of-long
Хотя в исходниках до сих пор можно встретить подобную ручную «оптимизацию», например, в IdentityHashMap.
String.hashCode
прописан в спецификации Java SE API, и другие реализации Java SE не вправе его менять. А то, во что switch превращается — отдаётся на откуп компилятору. И javac генерирует код, который на любой Java SE-совместимой реализации будет корректен.Как же так? Про
-XX:hashCode=N
уже миллион раз писали в блогах, твиттере, на Stack Overflow и пр.Объяснение про несовместимость Biased Lock с identityHashCode вообще жуткое: какие-то диаграммы состояний, перемещение заголовков, бла-бла-бла… Истинная же причина проста: в целях экономии места в заголовок помещается либо признак Biased-блокировки, либо identityHashCode. Только и всего.
MethodHandle.invoke
, хоть и реализован по-другому, но делает примерно всё то же, что иMethod.invoke
, за исключением проверок доступа. Поэтому большого выигрыша сами по себе MethodHandles не дают. Чтобы получить максимальную выгоду отjava.lang.invoke
, имеет смысл MethodHandle преобразовать в экземпляр интерфейса с помощью LambdaMetafactory. И тогда вызов будет столь же быстрым, как и обычныйinvokeinterface
.