java程序运行时的内存空间,按照虚拟机规范有下面几项:

(1)程序计数器  

       指示下条命令执行地址。当然是线程私有,不然线程怎么能并行的起来。 不重要,占内存很小,忽略不计。

(2)方法区

      这个名字很让我迷惑。这里面装的其实是程序运行需要的类文件,常量,静态变量等。作用容易明白。

      程序运行时,执行代码先得装入内存,当然java好像是在第一次用到时才加载,这样可以避免装入无用的类,节省内存。

      在HosSpot上,方法区现今和永久代是同一个区域。我就这么理解了,虽然作者解释说其实这两者根本不是同一个概念。

      概念暂时不大关心,垃圾回收是实实在在工作中用到的。

(3)本地方法栈

      存储Native本地方法中用到的局部变量表和操作数栈,动态链接,方法出口等。作用和(4)中无区别,而且在HotSpot上本地方法栈与java虚拟机栈是合二为一的。

(4)Java虚拟机栈

      线程私有

      存储java方法中用到的局部变量表和操作数栈,动态链接,方法出口等。

      在实际工作中会遇到栈内存溢出,StackOverflowError,不过以我的经验,如果出现栈溢出,绝大多数都是死循环递归造成的。

(5)堆

     堆在各线程见是共享的。

     这个是用的最多的。有好多人甚至以为java运行的需要的内存就只有这个,果果-Xmx可以指定堆可分配的最大值。-Xms指定堆最小分配。

     如果-Xms堆不够用时,会自动扩展,当扩展到-Xmx的值,仍然不够,就内存溢出了。OutOfMemoryError。

     理论上所有的对象实例和数组都是在堆上分配的,但是JIT编译器可以聪明的做很多事情,也许有些对象的使用范围是局限在某些方法中的,这样就可以在栈上分配,

     毕竟栈上分配的内存管理要容易的多,用完即抛,不需要交给垃圾回收器来处理。

     当然,写代码的人最好有个谱,什么时候该局部变量,什么时候需要类变量,把自己写的破代码全交给编译器去吭哧吭哧优化,一方面它不能完全优化的完美,

     另一方面也占用cpu时间(哎,有感而发,破代码见得太多了)