一般问题:Java具有堆和本地堆栈。是否可以从堆中访问任何对象?

2022-09-03 12:21:05

我真的在研究按值传递和Java如何分配对象以及Java将对象放在堆栈上的作用之间的差异。

是否仍然可以访问堆上分配的对象?Java强制实施哪些机制来保证正确的方法可以从堆中访问正确的数据?

看起来,如果你是狡猾的,甚至可能在运行时操纵java字节码,那么你也许能够在你不应该的时候操纵堆中的数据?


答案 1

JVM 指令集中没有提供对堆的任意访问的指令。因此,字节码操作在这里对您没有帮助。

JVM 还有一个验证器。它检查每个方法的代码(当正在加载类时),以验证该方法不会尝试从执行堆栈中弹出比它推送到它上面的值更多的值。这可确保方法无法“看到”其调用方法所指向的对象。

最后,局部变量存储在每方法数组(称为“局部变量数组”)中。同样,验证程序确保该数组的每个读/写指令都指定一个小于数组大小的索引。请注意,这些 JVM 指令只能指定常量索引。它们不能获取计算值并将其用作索引。

因此,回顾一下,答案是否定的。


答案 2

Java 中的所有对象都位于堆上。我不太确定你所说的“从堆中访问对象”是什么意思。堆栈上存储的唯一内容是调用当前上下文的函数列表及其局部变量和参数。所有局部变量和参数都是基元类型或引用。

如果 using 分配对象(这是分配非基元类型的唯一方法;是的,这包括数组类型),则对象将分配在堆上,并且对该对象的引用存储在堆栈或堆上,具体取决于引用是存储在局部变量/参数中还是作为另一个对象的成员。new

当作为参数传递给函数时,所有对象都通过引用传递 - 如果函数修改参数,则原始对象也会被修改。同样,也可以说对象引用是按值传递的 - 如果更改参数以引用新对象,它将在函数期间继续引用该对象,但传入的原始对象仍将引用它之前引用的任何内容。基元类型也按值传递。