Как получить адрес памяти кучи Java? - PullRequest
7 голосов
/ 13 мая 2009

Как определить адрес в памяти кучи Java для JVM, работающей в текущем процессе? То есть получить указатель void * или эквивалентную непрерывную область памяти, выделенную JVM для кучи с использованием Java, C или других вызовов?

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

Я бы хотел использовать свой процесс для изучения взаимодействия между кучей Java и представлением памяти Matlab и выяснить, когда он движется из-за изменения размера, предпочтительно всего изнутри процесса. Для этого нужен адрес кучи. Легко найти размер кучи из java.lang.Runtime, но не его адрес в памяти. Как это можно сделать?

Я использую Sun JRE 1.6.0_04 в процессе Matlab R2008b на Windows XP и Server 2003. Я понимаю, что это, вероятно, метод, зависящий от поставщика. Процесс запускает код, который мы написали, поэтому мы можем использовать пользовательский код Java, Matlab, JNI и C / C ++. Вызовы методов Java или поддерживаемые перехватчики в JVM предпочтительнее хакерских атак низкого уровня.

РЕДАКТИРОВАТЬ: Цель этого состоит в том, чтобы исследовать взаимодействие между GC JVM и GC Matlab. Мне не нужно заглядывать в кучу Java, и я не буду ничего читать из этой памяти; Я просто хочу посмотреть, где он находится в контексте общего пространства виртуальной памяти, в которое GC Matlab также пытается вписать данные.

Ответы [ 5 ]

2 голосов
/ 08 июля 2009

Быстрый и грязный способ получить фактический адрес кучи JVM - это перейти в WinDbg, подключиться к JVM и выполнить одну команду! Address. Где-то около 0х2 ??????? (Различается между версиями jvm, но остается статичным для этой версии) будет большой VAD, помеченный PAGE_EXECUTE_READWRITE, это куча вашей JVM в памяти процесса.

Для подтверждения вы можете установить точку останова на kernel32! VirtualAlloc, и после инициализации JVM в модуле JVM.DLL вы нажмете на вызов VirtualAlloc, показывая, что jvm выделяет его кучу. Если вы проверите код вокруг этого звонка, вы увидите, как рассчитывается адрес.

2 голосов
/ 13 мая 2009

Немного отступив ... Можете ли вы пойти с кучей Java фиксированного размера? На этом этапе проблемы перераспределения и фрагментации исчезают.

В автономном вызове Java, который включает в себя указание чего-то вроде -Xmx500m и -Xms500m для кучи 500 МБ. Вы должны перевести это в то, что хочет Matlab.

1 голос
/ 13 мая 2009

Если вы просто хотите уменьшить кучу JVM, попробуйте поиграть с параметрами gc, такими как -XX: MaxHeapFreeRatio (см. http://java.sun.com/javase/technologies/hotspot/vmoptions.jsp)

Не думаю, что вы можете получить указатель на кучу Java с помощью JNI. Однако куча Java - это просто память, выделенная процессу Windows из одной из куч процесса.

Вы можете получить кучи процессов из своего кода C ++, используя функцию GetProcessHeaps (http://msdn.microsoft.com/en-us/library/aa366571(VS.85).aspx), а затем начать их просмотр с помощью функции HeapWalk. Есть хороший пример на http://www.abstraction.net/content/articles/analyzing%20the%20heaps%20of%20a%20win32%20process.htm. возможность определить, какие выделенные блоки используются кучей Java, путем поиска определенных шаблонов байтов (исходный код JVM может дать вам некоторые подсказки относительно того, что искать, но удачи в этом разобраться!)

0 голосов
/ 14 мая 2009

Я не думаю, что есть способ сделать то, что вы хотите, без использования настраиваемой JVM. Теоретически вы можете использовать OpenJDK и исправить его или включить некоторую трассировку (не уверен, что есть такая, которая соответствует вашим потребностям). Я думаю, что внешний инструмент мониторинга, такой как Process Explorer может решить вашу проблему

0 голосов
/ 14 мая 2009

ГХ может перемещать данные в любое время для сжатия памяти. Так что для объектов в куче Java нет фиксированной точки. Вы можете использовать ByteBuffer.allocateDirect (), который выделяет память в пространстве «C», а не в куче, и это фиксируется в памяти.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...