【问题标题】:General Question: Java has the heap and local stack. Can you access any object from the heap?一般问题:Java 有堆和本地堆栈。你可以从堆中访问任何对象吗?
【发布时间】:2010-09-22 07:03:32
【问题描述】:

我确实在研究按值传递与 Java 如何分配对象以及 java 将对象放入堆栈之间的区别。

有没有办法访问堆上分配的对象? java 强制执行哪些机制来保证正确的方法可以访问正确的堆外数据?

如果你很狡猾,甚至可能在运行时操纵 java 字节码,你可能能够在不应该的时候操纵堆外的数据?

【问题讨论】:

  • 好问题——我希望我对 java 有更多的了解;一个好的答案将是我启蒙的开始:)

标签: java jvm stack heap-memory


【解决方案1】:

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

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

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

【讨论】:

  • 还有其他分配新对象的方法(克隆、Class.newInstance()、反序列化),但它们最终都在堆上。
  • “也可以说对象引用是按值传递”的解释是唯一准确的解释。说对象通过引用传递是不准确的。基本上Java只有传值,就像C一样。
【解决方案2】:

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

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

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

总而言之,答案是否定的。

【讨论】:

  • 我刚回到这个。所以基本上 Java 和类似的垃圾收集、基于堆栈的语言的结构是这样的,当你没有访问权限时,你不能随意访问堆的一部分。
【解决方案3】:

关于堆栈上的对象,只有来自 SUN 的新 Java 6 VM(可能还有其他一些虚拟机)会尝试通过将对象放入堆栈来优化字节码。通常,所有对象都将进入堆。供参考,请查看:http://www.ibm.com/developerworks/java/library/j-jtp09275.html

JVM 规范也位于http://java.sun.com/docs/books/jvms/second_edition/html/Overview.doc.html#6348。 JVM 通过简单地不给你破坏它所需的指令来保护它的堆。 JVM 实现中的缺陷可能会导致您的里程数有所不同。

【讨论】:

  • 我不同意 Java 6 cmets。逃逸分析的新特性可能允许 JVM 避免创建对象。因此,对象(int、float、引用等)的原始组件最终会出现在堆栈上。对象只存在于堆中。期间。
  • IBM 的另一个页面ibm.com/developerworks/library/j-jtp01274.html 不同意你的观点,John M。看来Java 确实可以在堆栈上分配对象。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-10-22
  • 1970-01-01
  • 2015-12-18
  • 2014-05-27
  • 1970-01-01
  • 2012-03-24
  • 2019-10-16
相关资源
最近更新 更多