Java内存区

一.概图:

 

java 自带分析堆内存工具 java堆内存分配_方法区

二.Java堆:

       1.Java对为线程共有。

       2.Java堆是线程共享的内存区域,几乎所有的对象实例和数组都要在堆上分配。说几乎是因为随着JIT编译器的发展和           逃逸分析技术的成熟,有一些对象实例在考虑到速度优化上,会采用栈上分配等。还有,不管是类属性的对象还是局部    对象,都是分配在Java堆的。

       3.Java堆是垃圾收集器管理的主要区域

       4.从垃圾回收角度看,Java堆可以分成新生代和老年代。

       5.当向堆申请一个对象内存空间时,如果在堆中无法完成实例分配,并且对也无法再扩展是,会抛出OutOfMemoryError       异常,即OOM。

二.Java虚拟机栈:

       1.虚拟机栈为线程私有的,其生命周期与线程相同。

       2.虚拟机栈是Java方法执行的内存模型。每个方法在执行的同时会创建该方法的一个栈帧(关于栈帧内容看栈帧的介绍),     每个方法的调用到执行完成相当于栈帧的到栈到出栈的过程。

       ps:因为Java虚拟机工程师在当初创建Java虚拟机的时候肯定是对物理机(称微机)的原理有相当好的连接,所以在介    绍Java虚拟机的同时多跟微机原理对比。这样有助于学习,理解。

       微机对方法的调用是,先把当前代码段的IP指针地址push进堆栈,即进行现场保留,然后再进行方法的调用,当方法              返回时,再把堆栈里保存的程序IP返回当前代码执行。

       3.如果线程请求的栈深度对于大于虚拟机栈允许的栈深度时,就抛出StackOverFlowError。虚拟机可以动态扩展,但是如    果扩展时无法申请到足够的内存时,就会抛出OutOfMemoryError。

三.本地方法栈:

       1.本地方法栈为线程私有的。

       2.本地方法栈与虚拟机栈功能很相似。只不过是Java虚拟机栈执行的是Java方法服务,本地方法栈执行的是native方法    服务。

       3.JVM对本地方法栈中使用的语言等没有强制规定。

       4.也会抛出StackOverFlowError,OutOfMemoryError。

四.方法区:

       1.方法区是内存共享的。

       2.方法区用于储存被虚拟机加载的类信息;常量;静态变量;JIT即时编译器编译后的代码等数据。

       注意,当我们在定义静态对象变量时,方法区储存的是该变量的引用reference,而对象的实例还是在Java堆中分配内存    的。当然,静态变量只能在类属性中定义,而不能在局部方法中定义。

       3.方法区也有垃圾回收机制。

       4.会抛出OutOfMemoryError。

       5.运行时常量池(也属于方法区)。

              1.属于类信息的一部分

              2.用于存放编译期生成的各种字面量,符号引用,直接引用。

              3.具有动态特性,即运行时可以将新的常量放入池中,如String.intern()。

              4.会抛出OutOfMemoryError。

五.程序计数器:

       1.线程私有。该部分只占了很小的内存。

       2.程序计数器相当于一个指针,指向当前线程程序运行的位置。

       3.如果线程正在执行Java方法,则程序计数器指向的是正在执行的虚拟机字节码地址;如果线程正在执行的是native方           法,则计数器为空。

       4.该部分是唯一一个Java虚拟机规范中没有规定OutOfMemoryError情况的区域。

五.直接内存:

       1.直接内存不是Java虚拟机规范中定义的内存区域。

       2.可以直接在native里分配内存,而不受虚拟机内存限制。

       3.既然是内存,还是会受到内存限制的,如本即RAM大小等。所以会抛出OutOfMemoryError。

       4.NIO就是使用直接内存的例子。NIO使用native函数库直接分配堆外内存,然后通过Java堆中的DirectByteBuffer对        象作为这块内存的引用操作。这也是NIO与就IO的性能差别的一个地方。