5

我试图完全理解 Java 如何使用它的内存安排。网上的讨论很混乱,有时会互相矛盾,所以我找不到可以信任的人。如果它与静态、静态方法、局部变量、线程、易失性等混合在一起,这个东西可能会非常复杂。所以我在想是否有一种方法可以让我自己研究我做一些 Java 编码实验。一个类 MemoryTrack 做这样的事情,

public myMethod(){
int i = 0;
MemoryTrack.show(new myClass()); //print out "Heap at address 111"
MemoryTrack.show(new myClass()); //print out "Heap at address 222"
MemoryTrack.show(i); //print out "Stack at address 333"
MemoryTrack.show("a static method");  //print out "stack at address 444"
}
4

4 回答 4

7

Java 虚拟机规范的第 2.5 节描述了内存的使用。堆栈存储堆栈帧(包含局部变量和部分结果)。堆是所有类实例和数组的来源。堆栈帧也可以从堆中分配(然后压入堆栈)。还有方法区和运行时常量池内存。详细信息在规范中详细说明。

就监控内存使用而言,一些分析器有相应的工具。要从程序内部进行监视,请查看MemoryMXBean类(以及java.lang.management包中的相关类)。它非常易于使用。虽然它可能无法为您提供您想要的一切,但它可能是最好的。

于 2012-11-01T17:34:59.433 回答
3

规则很简单:堆包含对象,栈包含局部变量和方法参数。对象字段位于对象内部,在堆中。不知道静态字段。方法和构造函数不存储在堆栈中,也不存储在堆中。线程和 volatile 无关紧要。

方法调用在堆栈上。每个都有一个为其保留的空间,即堆栈帧,其中包含局部变量和参数。

于 2012-11-01T17:35:17.343 回答
1

你需要知道的两件事

  • 它没有你想象的那么复杂。
  • 99%的时间都没有关系。

变量总是在栈上。

对象总是在堆上。(有例外,但我不会担心)

方法和类总是在 perm gen 中。

在 HotSpot/OpenJDK JVM 中,静态字段被收集在类的单例对象中。如果您执行堆转储,您可以看到该实例。其他 JVM 可能会以不同的方式执行此操作。

一个类 MemoryTrack 做这样的事情,

这样的方法不会做任何有用的事情,因为参数将始终在堆栈上,而它所引用的对象将始终在堆上。您无法以标准方式获取 Object 的内存位置,并且如果这样做的话也不太可能有用,因为它可以随时更改。

于 2012-11-01T18:46:33.500 回答
-1

您可能认为 Java 中的所有变量都在堆上。实际上它是依赖于实现的。

于 2012-11-01T17:37:49.223 回答