Рубрики
Без рубрики

Сжатые УПС в JVM

Узнайте, как настроить JVM для более эффективного использования памяти и адресации 32 ГБ кучи даже в 32-разрядной системе.

Автор оригинала: Ali Dehghani.

1. Обзор

JVM управляет памятью для нас. Это снимает с разработчиков бремя управления памятью, поэтому нам не нужно вручную манипулировать указателями объектов , что, как оказалось, отнимает много времени и подвержено ошибкам.

Под капотом JVM включает в себя множество изящных трюков для оптимизации процесса управления памятью. Одним из трюков является использование Сжатых указателей , которые мы рассмотрим в этой статье. Во-первых, давайте посмотрим, как JVM представляет объекты во время выполнения.

2. Представление объектов среды выполнения

JVM HotSpot использует структуру данных, называемую oops или Обычные указатели объектов для представления объектов. Эти oops эквивалентны собственным указателям на C. | instanceOop s-это особый вид ооп , который представляет экземпляры объектов в Java . Кроме того, JVM также поддерживает несколько других продуктов , которые хранятся в дереве исходных текстов OpenJDK|/.

Давайте посмотрим, как JVM выкладывает instanceOop s в память.

2.1. Компоновка памяти объектов

Компоновка памяти instanceOop проста: это просто заголовок объекта, за которым сразу следует ноль или более ссылок на поля экземпляра.

Представление JVM заголовка объекта состоит из:

  • Одно слово метки служит многим целям, таким как Предвзятая блокировка , Хэш-значения идентификаторов, и GC . Это не ооп, но по историческим причинам он находится в дереве исходных текстов OpenJDK ооп|/. Кроме того, состояние слова метки содержит только uintptr_t , поэтому его размер варьируется от 4 до 8 байт в 32-разрядных и 64-разрядных архитектурах соответственно Одно, возможно сжатое, слово класса
  • , которое представляет указатель на метаданные класса. До Java 7 они указывали на Постоянное поколение , но начиная с Java 8 они указывают на Метапространство 32-разрядный пробел
  • для принудительного выравнивания объектов. Это делает макет более удобным для аппаратного обеспечения, как мы увидим позже

Сразу после заголовка должно быть ноль или более ссылок на поля экземпляра. В этом случае word является собственным машинным словом, поэтому 32-разрядный на устаревших 32-разрядных машинах и 64-разрядный на более современных системах.

Заголовок объекта массивов, в дополнение к словам mark и klass, содержит 32-разрядное слово для представления его длины.

2.2. Анатомия отходов

Предположим, мы собираемся перейти от устаревшей 32-разрядной архитектуры к более современной 64-разрядной машине. Во-первых, мы можем ожидать немедленного повышения производительности. Однако это не всегда так, когда речь идет о JVM.

Основным виновником такого возможного снижения производительности являются ссылки на 64-разрядные объекты. 64-разрядные ссылки занимают в два раза больше места, чем 32-разрядные ссылки, поэтому это приводит к большему потреблению памяти в целом и более частым циклам GC. Чем больше времени отводится циклам GC, тем меньше срезов выполнения процессора для наших потоков приложений.

Итак, должны ли мы вернуться и снова использовать эти 32-битные архитектуры? Даже если бы это был вариант, мы не могли бы иметь более 4 ГБ пространства кучи в 32-разрядных пространствах процессов без дополнительной работы.

3. Сжатые УПС

Как оказалось, JVM может избежать потери памяти, сжимая указатели объектов или oops, так что мы можем иметь лучшее из обоих миров: позволяя более 4 ГБ пространства кучи с 32-битными ссылками на 64-битных машинах!

3.1. Базовая оптимизация

Как мы видели ранее, JVM добавляет заполнение к объектам так, чтобы их размер был кратен 8 байтам. С этими дополнениями последние три бита в oops всегда равны нулю. Это связано с тем, что числа, кратные 8, всегда заканчиваются 000 в двоичном коде.