Pull to refresh

Comments 24

Гораздо более внятное исследование, а не гадание на кофейной гуще. Интересно.

P.S.: байтики привычнее смотреть в HEX.
По-моему, это и есть гадание. Один «magic» чего стоит. Правдивую информацию можно почерпнуть в исходниках, благо, что открытые.

Заголовок Java-объекта, действительно, состоит из 2х слов.
Первое — markOop — многофункциональное хранилище разнообразной информации об объекте.
В зависимости от ситуации может содержать
— хеш-код объекта;
— возраст (количество пережитых GC);
— lock (обычный, рекурсивный или biased).
Подробное описание с побитовыми схемами — в комментариях к markOop.hpp.

Второе слово — указатель на класс. Но не тот, который java.lang.Class, а klassOop — нативное описание типа объекта. Что из себя представляет Klass, можно вычитать, опять же, в комментариях к klass.hpp. В частности, Klass содержит и java_mirror — ссылку на java.lang.Class.

У массивов сразу за этими двумя словами заголовка идет 32-битная длина массива — см. arrayOop.hpp.

Что касается полей объекта, они переупорядочиваются для экономии занимаемого места с учетом выравнивания. long и double поля должны быть выровнены по 64-битной границе, int и float — по 32-битной, short и char — по 16-битной, а затем уже и byte с boolean. Для некоторых системных классов (например, String, Throwable, Reference), с которыми тесно взаимодействует VM, уплотнение полей не применяется.
Разве хорошо воровать чужой текст?

wasm.ru/article.php?article=unsjav1

Вот на памят исходный текст автора, если он его изменит:
"
Все эксперименты проводились с использованием утилитарного класса Unsafe.
Малоизвестный класс sun.misc.Unsafe входит в комплект Sun Java Runtime начиная с первых версий. Как и все остальные классы в package sun.*, Unsafe не документирован, но имена (в большинстве своем нативных) функций, видимые при декомпиляции, говорят сами за себя. Явно присутствуют функции работы с памятью (allocateMemory, freeMemory,...), чтения и записи значений по заданному адресу (putLong, getLong,...) и некоторые более специализированные (throwException, monitorEnter, ...).

"
Капитанский кусок про то, что такое Unsafe.
В свое время руководствовался этим текстом.
Не хорошо.
Мне не стыдно.
Не только этот кусок…
P.s. дальше по тексту еще очень много плагиата
Да и хостинг с картинкой для привлечения внимания не выдержал и показывает соответствующую заглушку
На char тоже 4 байта?
И где хранятся поля монитора объекта?
>И где хранятся поля монитора объекта?

В «magic». Попробуй добавить synchronized(v) {… }.
Вернее, там не сам монитор, а сам факт блокировки + поддержка biased locks.
Меня интересует вопрос: с помощью unsafe можно ли из AccessController.doPrivileged секции запланировать или сразу послать на исполнение любой код просто записывая байтики по адресу в памяти, тем самым обходя всевозможные ограничения безопасности jvm?
Включенный security manager не даст вам выстрелить себе в ногу.
Я боюсь пользовательских скриптов, которые выполняются в jvm основного приложения. Если security manager запрещает прямую запись в память, то это успокаивает.
В любом случае никак невозможно защититься от таких вещей как new byte[1000000000] и for(;;) { }
Пользовательские скрипты можно загружать своим загрузчиком и просто отсекать «небезопасные» классы.
Выше описанным путем мне удавалось поменять байткод уже загруженных методов классов, меняя значения байт инструкций в памяти. Если будет время, дополню статью.

Насчет SM — я ничего не поверял, но я не думаю, что он вообще позволить лезть в память.
Надеюсь, изменение байткода методов класса в памяти делалась только «фану ради».
Потому что из-за тех, кто использует подобные трюки в реальных приложениях бог не просто убивает котенка, а выжигает кошачьи деревни напалмом.
Я говорил о случае, когда Java-программист модифицирует сырую память нелегальными способами (например через Unsafe или JNI), чтобы изменить байткод загруженных в память методов.

Саму же подмену тел методов, модификацию байткода, генерацию классов в процессе исполнения через существующий API преступлением, конечно же, не считаю.
Hotspot != Java
OpenJDK != Java
...
!= Java

Отличайте уже наконец язык от его реализации, в топике вы говорите исключительно об реализации.
<any JVM implementation> != Java

p.s. вот и меня хабрапарсер покарал
Я бы сократил всю статью до «С помощью sun.misc.Unsafe можно читать байты из памяти и получать адреса объектов».

Структура Java-объектов это даже не просто JVM-implementation-specific, а, вообще говоря, JVM-implementation-version-and-target-platform-specific, т.к. ничто не мешает тому же Oracle, например, полностью переделать структуру объектов в HotSpot'е к следующей мажорной версии Java.

Кстати, magic — это уникальная константа, для идентификации каких-либо структур данных, объектов (например, для проверок перед кастами или для отладки).
То, что вы назвали magic'ом — просто поле с набором флагов, но никак не magic.
Sign up to leave a comment.

Articles