我真的在研究按值传递与 Java 如何分配对象以及 java 将对象放入堆栈中的作用之间的区别。
无论如何可以访问堆上分配的对象吗?java 强制执行哪些机制来保证正确的方法可以访问堆外的正确数据?
看起来如果您很狡猾,甚至可能在运行时操纵 java 字节码,那么您可能能够在不应该的时候操纵堆外的数据?
我真的在研究按值传递与 Java 如何分配对象以及 java 将对象放入堆栈中的作用之间的区别。
无论如何可以访问堆上分配的对象吗?java 强制执行哪些机制来保证正确的方法可以访问堆外的正确数据?
看起来如果您很狡猾,甚至可能在运行时操纵 java 字节码,那么您可能能够在不应该的时候操纵堆外的数据?
JVM 指令集中没有指令可以任意访问堆。因此,字节码操作在这里对您没有帮助。
JVM 也有一个验证器。它检查每个方法的代码(当一个类被加载时),以验证该方法不会尝试从执行堆栈中弹出比它推入它的值更多的值。这确保了一个方法不能“看到”其调用方法所指向的对象。
最后,局部变量存储在每个方法数组(称为“局部变量数组”)中。同样,验证器确保从/到该数组的每个读/写指令都指定一个小于数组大小的索引。请注意,这些 JVM 指令只能指定一个常量索引。他们不能获取计算值并将其用作索引。
回顾一下,答案是否定的。
Java 中的所有对象都位于堆上。我不太确定“从堆中访问对象”是什么意思。唯一存储在堆栈中的是调用当前上下文的函数列表及其局部变量和参数。所有局部变量和参数都是原始类型或引用。
如果您使用new
(这是分配非原始类型的唯一方法;是的,这包括数组类型)分配对象,则该对象将分配在堆上,对该对象的引用存储在堆栈或堆中,取决于引用是存储在局部变量/参数中还是作为另一个对象的成员。
当作为参数传递给函数时,所有对象都是通过引用传递的——如果函数修改了参数,那么原始对象也会被修改。同样,也可以说对象引用是按值传递的——如果您将参数更改为引用一个新对象,它将在函数执行期间继续引用该对象,但传入的原始对象仍将引用它之前提到的任何内容。原始类型也按值传递。
关于堆栈上的对象,只有来自 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 实现中的缺陷可能会导致您的里程有所不同。