Показаны сообщения с ярлыком java sizeof. Показать все сообщения
Показаны сообщения с ярлыком java sizeof. Показать все сообщения

суббота, 5 марта 2011 г.

sun.misc.Unsafe - немного магии вокруг JVM

Когда-то, выбирая декомпилятор, натолкнулся я на несколько изумительных статей на wasm.ru. Статьи они кажется потерли, или по крайней мере изменили адреса, но сохранили их в виде вордовского файла, который можно загрузить отсюда:



Описывают, что такое Unsafe api, предоставляющее программисту возможность работать с классами, методами и т.п. ниже того уровня , который позволяют штатные средства платформы Java - на фактически на уровне тех самых С-структур, которые используются внутри JVM для предоставления сущностей класс, инстанс класса, метод и т.п.

Что дает возможность делать многие вещи, которые в программировании на Java  "традиционно" считаются невыполнимыми - функция sizeOf, (возвращающая точный размер объекта в памяти , взятый напрямую из поля  структуры, которая представляет этот объект внутри JVM), наследования от final-класса (делается двумя шагами по сути -  в список предков класса добавляется нужный нам класс, и из таблицы модификаторов доступа для этого суперкласса во время выполнения программы удаляется final - и

всего делов ;)).



Ну и уже более изощренные и хакерские штучки - самомодицирующиеся во время выполнения методы..и т.п. Очень рекомендую эти статьи к прочтению :).

Да, конечно -- смещения полей в структурах высчитываются на пальцах, класс sun.mics.Unsafe недокументирован (но присутствует в Java с самого ее начала, и очень навряд ли будет из нее удален - я очень сильно подозреваю, что предоставляемые им низкоуровневые возможности используются инструментами типа отладчиков и т.п.), и в продакшне ни один Project Manager такое использоватьне позволит -- да и не требуется в обычных приложения никогда столь низкоуровневый доступ к JVM. Но знать, как ява-машины работает с классами внутри себя -- полезно и интересно, а знать что из обычной программы на чистой яве можно получать доступ такого уровня -- еще интересней.

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

Я не думаю, что это дыра в системе безопасности Java. Собственно, суммирую и повторю описанное в первой из статей.
Итак. Есть две точки входа для получения инстанса класса Unsafe, который позволит нам творить черную магию:

1) Получить его можно через Unsage.getUnsafe() - НО! только в том случае, если вызывающий класс был загружен первичным класслоадером (www.tedneward.com/files/Papers/BootClasspath /BootClasspath.pdf - тут можно прочитать подробней про иерархию класслоадеров). Это сделать несложно -- всего-то добавить ключ -Xbootclasspath в список стартовых опций ява-машины. Но для этого надо иметь доступ  к среде выполнения.

2) Можно просто взять private переменную theUnsafe - которая хранит инстанс класса Unsafe внутри него. Но если есть Security Manager и установлена для него соответствующая политика запрещения опасной рефлексии , получить значение этой закрытой переменной не удастся.

Соответственно, мой вывод -- это API не является уязвимостью в JVM, вовсе нет.
Потому что точно так же рефлексией (если она не запрещена в политиках безопасности) можно творить безобразия внутри приложения, но и польза от нее может быть большая-- надо просто разумно выставлять политики безопасности в каждом конкретном случае.

Да - Unsafe API дает беспрецедентный уровень доступа к среде выполнения Java из программы. Но чтобы получить доступ к этому апи -- надо либо иметь соотв. права на той машине, где выполняется приложение (например, возможность задавать параметры запуска ява-машины), либо должен быть соответственно сконфигурирован (без учета этой опасности) Security Manager.