如何确定当前进程中运行的JVM的Java堆内存地址?也就是说,使用Java,C或其他调用获取一个void *指针或等效于JVM为堆分配的内存的连续区域?
Matlab在其进程中嵌入了JVM。 JVM分配的内存对于Matlab数组是不可用的,而且这一点很重要,因为它占用了大量连续的内存并且从不收缩,而Matlab也需要连续的内存用于其数组。如果在扩展期间重新分配堆,则可能导致碎片。
我想检查我的进程来检查Java堆和Matlab的内存视图之间的交互,并找出它由于调整大小而移动的时间,最好是在进程内部。这需要堆的地址。从java.lang.Runtime很容易找到堆大小,但在内存中找不到它的地址。怎么办呢?
我在Windows XP和Server 2003上的Matlab R2008b进程中运行Sun的JRE 1.6.0_04。我意识到这可能需要是特定于供应商的技术。该过程运行我们编写的代码,因此我们可以使用自定义Java,Matlab,JNI和C / C ++代码。 JVM中的Java方法调用或受支持的钩子优先于低级别的hackery。
编辑:这样做的目的是检查JVM的GC和Matlab的GC之间的交互。我没有必要查看Java堆,也不会从该内存中读取任何内容;我只是想知道在整个虚拟内存空间的上下文中,Matlab的GC也试图将数据放入其中。
答案 0 :(得分:2)
退一步......你可以选择固定大小的Java堆吗?那时对重新分配和分裂的担忧消失了。
在独立的Java调用中,涉及为500Mb堆指定-Xmx500m和-Xms500m之类的东西。你必须把它翻译成matlab想要的东西。
答案 1 :(得分:2)
获取JVM的实际堆地址的快速方法是跳转到WinDbg,附加到JVM并发出单个!地址命令。大概在0x2左右??????? (它在jvm版本之间存在差异,但对于该版本保持静态)将是一个标记为PAGE_EXECUTE_READWRITE的大型VAD,这是您进程内存中的JVM堆。
要确认,您可以在kernel32!VirtualAlloc上设置断点,并在模块JVM.DLL中启动JVM后,您将点击对VirtualAlloc的调用,向您显示其堆的jvm分配。如果您查看此调用的代码,您可以看到地址的计算方式。
答案 2 :(得分:1)
如果您只想让JVM堆缩小,可以尝试使用gc参数,例如-XX:MaxHeapFreeRatio(参见http://java.sun.com/javase/technologies/hotspot/vmoptions.jsp)
我认为你不能用JNI获得指向Java堆的指针。但是,Java堆只是Windows从其中一个进程堆分配给进程的内存。
您可以使用GetProcessHeaps函数(http://msdn.microsoft.com/en-us/library/aa366571(VS.85).aspx)从C ++代码中获取进程堆栈,然后使用HeapWalk函数开始遍历它们。在http://www.abstraction.net/content/articles/analyzing%20the%20heaps%20of%20a%20win32%20process.htm有一个很好的例子。您可以通过查找某些字节模式来确定Java堆使用了哪些已分配的块(JVM源代码可能会为您提供有关查找内容的一些线索,但祝您好运!)
答案 3 :(得分:0)
GC可以随时移动数据以压缩内存。因此,Java堆中的对象没有固定点。您可以使用ByteBuffer.allocateDirect()在“C”空间而不是堆中分配内存,并将其固定在内存中。
答案 4 :(得分:0)
如果不使用自定义的JVM,我认为没有办法实现您的目标。理论上你可以使用OpenJDK并对其进行修补或启用一些跟踪(不确定是否有符合您需求的跟踪)。我认为the process explorer等外部监控工具可以解决您的问题