有没有办法找到Java程序访问的内存地址和顺序?

时间:2012-07-23 09:16:26

标签: java instrumentation

我想研究Java程序的内存访问模式。是否有框架或方法可以实现这一目标。

假设有一个程序P,它按顺序访问内存地址m1,m2,m3等。我希望能够按顺序看到这些访问,如果可能的话,还能访问哪种类型的对象?

更新(添加Durandal的建议):

我总是可以通过使用PIN工具运行Java程序来找到内存访问模式。除了这样做之外,这一切都很好,我将丢失内存地址到对象的映射。我想要做的一个重要方面是能够将内存使用情况与相应的类型(Class)进行映射。

虽然正确地提到内存使用模式将取决于JVM实现,但我想将其视为本研究的后续步骤。现在,我正在寻找字节码检测。 (如果我的方向错误,请纠正我!)

我如何看待字节码检测将帮助我分析缓存使用情况? 在解释之前!这只是我想要做的一个方面。当存储器访问模式(从PIN或修改的VM或其他任何方式获得)不足以向我提供有关不同对象(或属于特定类的对象)使用缓存的信息时,我会这样做。 。假设我将字节码访问作为

ObjectA
ObjectB
ObjectC
...

很容易找到对象的大小。我还可以找到对象的内存访问是否是内存分配,如果这是对对象的第一次访问。然后,假设运行时JVM将分配连续内存,我可以假设缓存的使用(通过运行缓存模拟)。现在,这不是一个非常好的假设,但仍然给我一个缓存使用的上限(至少我相信如此)。

2 个答案:

答案 0 :(得分:2)

嗯,你总是可以这么做:改变虚拟机。有些JVM实现完全用Java编写,可能会被改变以收集您想要的数据。

但是,我坚信内存访问模式将在运行程序的特定VM上依赖依赖(因为它们会在内存中以不同的方式对数据进行粒化)。不同的VM =不同的访问模式。如果您测量的VM具有JIT,则还将取决于JIT是否启动。

真正收集所有内存访问的方法是在某种沙箱环境中运行VM并计算其访问权限(这可以在某些模拟器中完成,或者借助于MMU)。


编辑(问题更新 - 仅限字节码检测):使用字节码检测,您基本上非常接近仪器分析器的功能。您现在面临的主要问题是您无法轻松建立对象和内存地址之间的关系。我可以想出两种方法来规避这个:

  • 有一个(JRE私有,但可用)类sun.misc.Unsafe,可以获取对象,字段和数组的绝对内存地址(它有很多方法可以做到这一点)。如果您检测字节码以调用实用程序方法进行计数,则可以使用“不安全”来确定将使用的地址。但是,Unsafe是特定于实现的,垃圾收集器可能会在堆周围移动对象时出现问题。这可能是您想要衡量的,也可能不是。至少可以通过合理的努力来实现。

  • 您可以完全放弃内存地址的概念,并将其替换为对象标识字段(分别为数组标识和索引) )。然后,您的分析工具需要跟踪对象和访问的字段。您真正需要注意的唯一事情是您必须以不会阻止垃圾收集器的方式保留对象引用(例如,使用WeakReferences)。这也不应该太难实现。此方法无法识别热内存位置,而是热对象/字段

两种方法都会对测量产生一些影响,因为收集的数据将与分析的代码存储在同一个堆中。如果这是非常不受欢迎的,您可以使用JNI在堆外收集数据。

答案 1 :(得分:0)

Java程序的哪个部分? Java“用户空间”由加载的类组成,以前可由“public static void main(String [] args){...”或整个JVM访问,包括幕后内存管理,垃圾收集,调试设施,管理设施等。

如果您正在寻找真实的内存地址,那么您需要调试JVM。这与调试Java程序非常不同,因为在真实存储器和“用户空间”程序之间存在存储器抽象层。要调整实际内存访问,不能重写Java程序,需要重写JVM。

字节码插入仍然是“用户空间”Java程序的一部分,这意味着您永远无法通过字节码插入来确定绝对内存地址。事实上,对于同一个对象,JVM引用到实际内存地址的“用户空间”映射甚至不会随着时间的推移而保持不变。