Создание пользовательской JVM с большим заголовком объекта

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

Итак, у меня есть среда в рабочем состоянии, я изменил некоторые простые вещи, чтобы сгенерировать некоторые обратные вызовы для того, что мне нужно, поиграл с некоторыми встроенными функциями, пока все хорошо.

Однако я хотел бы знать: что здесь эксперты JVM думают о возможности создания настраиваемой виртуальной машины с более крупным заголовком объекта (например, на 8 байт больше). markOop.hpp довольно хорошо объясняет содержание слова-метки для различных существующих вкусов (32-битные, 64-битные, 64-битные со сжатыми ой), и мне было интересно, насколько сложно будет расширить заголовок, чтобы я мог добавить дополнительную информацию объекты (без тегов не включена опция, см. мой пост здесь).

Поэтому, прежде чем копать глубже, я надеялся, что кто-нибудь, имеющий опыт в этом, сможет дать некоторую обратную связь. Например, это «самоубийственная миссия», потому что повсюду слишком много мест, где есть жестко закодированные предположения относительно размера заголовка и смещений? Или все это достаточно централизовано и может быть выполнено с разумными усилиями, не рискуя все сломать? Любой указатель на то, что может потребовать особого внимания и какие последствия это может иметь (помимо очень очевидного; большего потребления памяти)?


person Haasip Satang    schedule 17.11.2018    source источник


Ответы (1)


Определенно можно увеличить заголовок объекта (я видел такие эксперименты раньше), хотя это будет не так просто, как просто добавить новое поле в класс oopDesc ​​. Я считаю, что в коде JVM есть несколько мест, которые зависят от размера заголовка объекта, но их не должно быть слишком много. Размер заголовка объекта уже различается в зависимости от платформы и параметра UseCompressedOops, поэтому в большинстве мест в коде уже используются относительные смещения, и новое поле не пострадает.

Другой вариант - не расширять заголовок, а добавить новое поддельное поле в класс java.lang.Object. HotSpot уже имеет оборудование для добавления таких полей, ищите InjectedField в источниках. Однако и это будет нетривиально. Есть несколько жестко запрограммированных смещений для системных классов, см. JavaClasses :: check_offsets. Это тоже нужно исправить.

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

Услышав о вашем проекте, я думаю, у вас также есть третий вариант: отказаться от требования «только JVMTI» и переписать некоторые части агента на Java, используя возможности инструментария байт-кода и JIT-компиляции. Да, это может немного изменить выполняемый Java-код и, вероятно, привести к загрузке большего количества классов, но действительно ли это имеет значение, если с точки зрения пользователя влияние будет даже меньше, чем с агентом только для JVMTI? Я имею в виду, что влияние на производительность может быть значительно меньше, если нет собственных переключателей Java ‹->, накладных расходов JVMTI и так далее. Если у агента низкие накладные расходы и он работает со стандартной JVM, я думаю, не большая проблема - включить его в производственной среде, чтобы получить его классные функции, не так ли?

person apangin    schedule 25.11.2018
comment
Это почти именно то, что я реализовал тем временем :) Я изменил иерархию классов для всех классов, расширяющих java.lang.Object, чтобы вместо этого расширить MyObject. Новый класс содержит необходимые мне дополнительные поля. Я исключил классы, перечисленные в javaClasses.cpp, и добавил специальную обработку для этих случаев. Работает, как ожидалось, и пока не требует специальной сборки JVM. В любом случае мы рассмотрим вопрос заголовка объекта, просто чтобы узнать, как это можно сделать. - person Haasip Satang; 26.11.2018
comment
Что касается работы на Java, да, часть логики, использующей класс MyObject, написана на Java. Однако существует риск того, что мы повлияем на наш собственный двигатель. Поэтому нам действительно нужно убедиться, что код, который мы пишем, не приводит к какому-либо событию, которое будет отслеживаться, или нам нужно отключить трассировку для текущего потока, как только он входит в код нашего движка (вот как я это сделал в ранее POC). Учитываются такие вещи, как загрузка классов и порядок, записи мониторинга, собственные вызовы и результаты, клиники, ссылки и т. Д. Если что-либо из этого не синхронизируется между запусками, у нас проблемы. - person Haasip Satang; 26.11.2018
comment
@HaasipSatang Да, это типичная проблема для многих Java-агентов, и она обычно решается отключением инструментовки в коде агента - точно так, как вы описываете - например, установкой локального флага потока или чего-то подобного. - person apangin; 26.11.2018
comment
Поскольку мы все равно изменяем так много основных вещей, я сделал это, просто добавив boolean к java.lang.Thread, который указывал, отключен ли перехват событий или нет. Хотя это отлично работает, чтобы игнорировать такие события, как ввод монитора или собственные вызовы, на самом деле это не помогает, если такие вещи, как глобальный счетчик, обновляются или некоторые статические поля изменяются из-за некоторого кода, который мы используем. Не сказать, что это невозможно, просто сказал, что это было сложно и привело к множеству нежелательных побочных эффектов. Но если взглянуть на это еще раз, то сейчас главная проблема - производительность. - person Haasip Satang; 26.11.2018