JVM总结_JVM内存结构

1. JVM内存结构

  •  堆(Heap)

  •  方法区(Method Area)

  •  程序计数器(Program Counter Register)

  •  本地方法栈(Native Method Stack)

  •  虚拟机栈(VM Stack)

    

JVM内存结构

  •  堆(Heap)

堆是Java虚拟机中内存最大的一块区域,堆是被所有线程共享的一块区域。所有的对象实例及数组都要在堆上分配(但是对着JIT编译器的发展和逃逸分析算法的成熟,所有的对象实例及数组都在堆上分配这一点并不是那么绝对,关于这里的更多描述请看这里http://www.hollischuang.com/archives/2398)。

java堆中分为新生代和老年代。新生代中可以再细分为:伊甸园(Eden)、幸存1区(From Survivor)、幸存2区(To Survivor)。

JVM新生代结构

java堆在物理上不要求一定是连续的内存空间,只要逻辑上连续即可。既可以固定大小,也可以拓展。(通过-Xmx和-Xms控制)

  • 方法区(Method Area)

和堆(Heap)一样,方法区也被所有的线程共享。用于存储对象的类型信息,这些类型信息包括:虚拟机已经加载的类的信息、常量、静态变量。

方法区中还有一部分区域是运行时常量池(Runtime Costant Pool),用于存放编译期生成的各种字面量和符号引用,这些内容在完成类的加载后进入运行事常量池存放。但是常量并不是一定在编译期才能放入常量池中,在运行期产生的常量也可以放入常量池中,比如使用String的intern()方法(更多请见:https://mritd.me/2016/03/22/Java-%E5%86%85%E5%AD%98%E4%B9%8B%E6%96%B9%E6%B3%95%E5%8C%BA%E5%92%8C%E8%BF%90%E8%A1%8C%E6%97%B6%E5%B8%B8%E9%87%8F%E6%B1%A0/)。

JVM方法区结构

  • 程序计数器(Program Counter Register)

    程序计数器在JVM的空间较小,而且它是线程私有的。它可以看做是当前线程所执行的字节码行号指令器。正因为有了程序计数器,在多线程进行线程切换时,线程能够记住执行到了哪里。程序计数器也是JVM中唯一没有规定(不会抛出)OutOfMemoryError的情况的区域。

  • 虚拟机栈(VM Stack)

    虚拟机栈在JVM中也是线程私有的,它的生命周期与线程相同。每个方法执行的时候会创建一个栈帧(Stack Frame),用于存储局部变量表(Local Variable Table),操作数栈(Operand Stack),动态连接(Dynamic Linking),方法出口等信息。每个方法从开始调用到执行完成的过,就是对应的栈帧从入栈到出栈的过程。(更多可见https://iamjohnnyzhuang.github.io/java/2016/07/12/Java%E5%A0%86%E5%92%8C%E6%A0%88%E7%9C%8B%E8%BF%99%E7%AF%87%E5%B0%B1%E5%A4%9F.html)

    其中,局部变量表中存放了基本数据类型,和引用类型的对象指针和一套字节码指令的地址。其中long和double会占用两个局部变量的空间。局部变量的空间在编译期就完成了分配,并切不会在运行期间发生改变。

    虚拟机栈可能会发生一下两种异常:

        1. StackOverflowError:线程请求的栈深度大于虚拟机所允许的深度。

        2. OutMermoryError:栈扩展是无法再申请到内存。    

  • 本地方法栈(Native Method Stack)

    本地方法栈与虚拟机栈非常的相似,本地方法栈为虚拟机使用的Native方法服务。本地方法栈可以存放别的语言的方法。

  • 直接内存(Direct Memory)

    直接内存并不是JVM内存中的一部分,但是这一部分也会导致OutOfMemoryError异常.

后续继续完善

    

猜你喜欢

转载自my.oschina.net/u/3428296/blog/1822033