《深入理解JAVA虚拟机》笔记1
java程序运行时的内存空间,按照虚拟机规范有下面几项:
(1)程序计数器
指示下条命令执行地址。当然是线程私有,不然线程怎么能并行的起来。 不重要,占内存很小,忽略不计。
(2)方法区
这个名字很让我迷惑。这里面装的其实是程序运行需要的类文件,常量,静态变量等。作用容易明白。
程序运行时,执行代码先得装入内存,当然java好像是在第一次用到时才加载,这样可以避免装入无用的类,节省内存。
在HosSpot上,方法区现今和永久代是同一个区域。我就这么理解了,虽然作者解释说其实这两者根本不是同一个概念。
概念暂时不大关心,垃圾回收是实实在在工作中用到的。
(3)本地方法栈
存储Native本地方法中用到的局部变量表和操作数栈,动态链接,方法出口等。作用和(4)中无区别,而且在HotSpot上本地方法栈与java虚拟机栈是合二为一的。
(4)Java虚拟机栈
线程私有
存储java方法中用到的局部变量表和操作数栈,动态链接,方法出口等。
在实际工作中会遇到栈内存溢出,StackOverflowError,不过以我的经验,如果出现栈溢出,绝大多数都是死循环递归造成的。
(5)堆
堆在各线程见是共享的。
这个是用的最多的。有好多人甚至以为java运行的需要的内存就只有这个,果果-Xmx可以指定堆可分配的最大值。-Xms指定堆最小分配。
如果-Xms堆不够用时,会自动扩展,当扩展到-Xmx的值,仍然不够,就内存溢出了。OutOfMemoryError。
理论上所有的对象实例和数组都是在堆上分配的,但是JIT编译器可以聪明的做很多事情,也许有些对象的使用范围是局限在某些方法中的,这样就可以在栈上分配,
毕竟栈上分配的内存管理要容易的多,用完即抛,不需要交给垃圾回收器来处理。
当然,写代码的人最好有个谱,什么时候该局部变量,什么时候需要类变量,把自己写的破代码全交给编译器去吭哧吭哧优化,一方面它不能完全优化的完美,
另一方面也占用cpu时间(哎,有感而发,破代码见得太多了)