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的性能差别的一个地方。