При традиционном программировании на Java вам больше не придется иметь дело с объектами или местоположениями Java из памяти. Когда вы обсуждаете это на форумах, первый вопрос, который возникает: зачем вам знать адрес Java-объекта? Это правильный вопрос. Но в прошлом мы оставляли за собой право проводить испытания. Нет ничего плохого в изучении вопросов на неизведанной территории. Я придумал эксперимент с использованием пакетов компании Sun. Unsafe — это пакет, принадлежащий sun.misc. Возможно, этот пакет вам немного незнаком, взгляните на исходный код и методы, и вы поймете, о чем я говорю.
Управление безопасностью Java обеспечивает достаточную степень сокрытия, чтобы гарантировать, что вы не сможете так легко возиться с памятью. В качестве первого шага я подумал о том, чтобы получить местоположение объекта Java в памяти. До изучения я был на 100% уверен, что найти местоположение адреса объекта в Java невозможно.
Документация Sun Unsafe.java API показывает, что у нас есть доступ к адресу с помощью метода objectFieldOffset. Этот метод как бы говорит: «Класс в отчете выделяет свое местоположение в определенной области хранилища». В любом случае я могу выделить область памяти, в которой хранится объект, из хранилища его класса. Вы можете возразить, что мы получаем не абсолютный адрес физической памяти объекта. Однако мы получили логический адрес памяти. Следующая программа будет Вам очень интересна!
В качестве первого шага мне нужно получить объект класса Unsafe. Это сложно, потому что конструкторы частные. Существует метод getUnsafe, который возвращает небезопасный объект. Управление безопасностью Java требует, чтобы вы предоставили права доступа к исходному коду. Я использовал немного отражения и получил экземпляр. Я знаю, что есть более эффективные способы получить экземпляр, но я выбрал следующий метод, чтобы обойти управление безопасностью.
Чтобы использовать объекты Unsafe, просто вызовите objectFieldOffset и staticFieldOffset. Результатом является адрес выделения памяти класса.
Следующий пример программы может работать на JDK1.6.
общественный класс ObjectLocation {
частный статический int apple = 10;
частный int оранжевый = 10;
public static void main(String[] args) выдает исключение {
Небезопасно небезопасно = getUnsafeInstance();
Поле appleField = ObjectLocation.class.getDeclaredField("яблоко");
System.out.println("Местоположение Apple: "
+ unsafe.staticFieldOffset(appleField));
Поле OrangeField = ObjectLocation.class.getDeclaredField("оранжевый");
System.out.println("Местоположение Orange: "
+ unsafe.objectFieldOffset(orangeField));
}
частный статический Unsafe getUnsafeInstance() выдает SecurityException,
NoSuchFieldException, IllegalArgumentException,
IllegalAccessException {
Поле theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafeInstance.setAccessible(истина);
return (Unsafe) theUnsafeInstance.get(Unsafe.class);
}
}