我在CSDN论坛发的帖子,Java栈与堆又一篇烂文,主要想纠正【Java栈与堆一篇好文!! [推荐]】 的错误,希望初学者不被误导。
但是我发的那个帖子也有一些问题,文字上有一些错误和某个概念上的错误(随后解释),还有就是该帖子直接按照“一篇好文”的格式重写了一下,初学者不一定好理解文中的思路。
在自己的博客中重新整理一下。
----------------------------------------------------------
1、前述
**为什么要讨论Java 栈与堆(按照Java 2 Virtual Machine 规范,前者称为JVM stack,而后者heap取消了1版中出现的Java heap),主要是为了更好了解Java程序中各种变量(variables)的生命周期。也便于理解引用变量(如String str1)的==比较Vs相等比较 这种非常频繁出现在考试中的问题。
**讨论下面的问题时,要注意对“Java语言语义的理解”不同于“从JVM的角度去说明”。这是两个不同的思考层面,不同思考层面所关心的议题和术语都有所差别。不懂得站在不同思考层面思考和讨论问题,你就没有理解什么叫抽象。对于Java语言而言,最高思考层面是对象、下一个层面是接口/方法协议,最低一个层面是方法实现。
当然,The Java virtual machine is the cornerstone of the Java and Java 2 platforms.(Java虚拟机是Java和Java平台的基石),不深入了解JVM,你就不能真正清楚的了解Java语言实现背后的故事。You can be a good Java developer and never worry about that stuff. …… To be a great Java developer, you have to understand what the JVM is doing for you.
**你首先要知道 变量,引用和对象三者在Java语言中的含义。即:
变量是一个存储场所(A variable is a storage location. ),引用变量中保存的值是指向一个对象的引用。
引用(reference values 或简称reference )是引用变量的值、是new表达式的值、是对象的唯一识别号。 特别地,Each string literal is a reference (§4.3) to an instance (§4.3.1, §12.5) of class String (§4.3.3). JLS。(每一个字符串文字是一个指向类String(§4.3.3).的实例(§4.3.1, §12.5)的引用(§4.3)。《Java语言规范》);A String object has a constant, unchanging value. String literals (§2.3) are references to instances of class String. (JVM规范§2.4.8).
对象/类或数组的实例:对象是拥有状态、行为和身份识别的实体。An object is a dynamically created class instance or an array. The reference values (often just references) are pointers to these objects and a special null reference, which refers to no object. An object is created in the heap and is garbage-collected after there are no more references to it.
2、Java的内存分配策略 ()
当JVM运行一个程序时,它需要内存来存储很多东西,包括从装载的class文件中提取的字节码和其他信息、程序所实例化的对象、传递给方法的参数、返回值、局部变量和计算的中间结果。JVM将它执行程序所需的内存组织成runtime data areas 。忽略与程序执行相关的pc register (program counter) 和 native method stacks, Java程序中的各种数据的保存在3个地方:方法区(Method Area)、JVM stack和Java堆。
(1)方法区:源代码中的命名常量、String常量和static 变量的值保存在方法区中。关于成员变量的处理 。然而没有可查的文献说明“方法区是静态分配(static allocation)的”!
按照静态分配的解释,编译器将变量在绑定在某个存储位置上,而且这些绑定不会在运行时改变。但是如果考虑到类的卸载,方法区中保存数据的空间仍然可以在运行时回收,因此,方法区在逻辑上是堆的一部分(the method area is logically part of the heap, )。如果忽略类的卸载,特别对简单程序而言,方法区的内存分配策略非常类似于静态分配。
(这仍然可以说是我的一个概念上的错误,因此Java语言中基本就很少见到讨论静态分配、栈分配和堆分配这三种基本的内存管理策略的内容。或者说Java中只有栈分配和堆分配。)
(from The Art and Science of Java ,Chapter 7 The Object Memory Model)
(2)JVM Stack是一个逻辑上的概念,它以stack frame为push和pop的操作单元;Java虚拟机每调用一次方法就创建一个方法帧(frame),退出该方法则对应的方法帧被弹出(pop)。
<input id="sv_AObj_Plugin_Type_input" maxlength="2147483647" size="20" type="hidden" value="-1">