《深入理解java虚拟机》的内存模型个人理解

《深入理解java虚拟机》的内存模型个人理解
如图所示。内容看图实际上都说完了。图画的比较丑,但是意思都说明白了。。。
服务器/计算机的内存分配如果从JVM方向划分的话,大致分为三块:

  • 1.JVM内存区
  • 2.NIO内存区
  • 3.剩余其他内存区

其中针对JVM内存区粗略分为三部分。值得一说的是这些都是概念,模型上的认为划分,并不是虚拟机的物理分割!分别是占用内存比较少的程序计数器,栈(stack)和占用JVM内存最多的堆(Heap)。估计该有人疑问说我分错了。本地方法栈和方法区为啥划分到大堆和大栈里?其实按照功能划分这样也是可以的。在细分的话,堆分为java堆和方法区。栈分为java栈和本地方法栈。nio的内存区主要用来服务于channel和buffer的。文件流读取到内存,往通道里塞数据都需要内存,所以要单独分出来。
分别说下他们的功能:

  • 1.程序计数器

字节码解释器通过改变计数器的值来选取下一条需要执行的字节码指令。计数器可以看成当前线程对应字节码指令的行号指示器。计数器中存储的正在执行的虚拟机字节码指令的地址,如果是Native方法,值为空(undefined)。需要注意的是:每个线程都有自己独立的程序计数器。各条线程间是互不影响,独立存储。

  • 2.java栈
    java虚拟机栈是线程私有的。和线程是同生共死。说起这个java虚拟机栈。我们不得说下java方法执行时的内存模型:栈帧(stack frame)。栈帧是用来存储局部变量表,操作数栈,动态链接,方法出口等信息。一个java方法从调用到完成就对应一个栈帧在(虚拟机)栈的入栈和出栈。而在《深入理解java虚拟机》书中说的java栈,是说的局部变量表部分。
    局部变量表中存储着编译期各种基本类型,对象引用(reference,可以是引用句柄或者直接指针)
  • 3.本地方法栈
    本地方法栈和java栈发挥的作用类型。要理解本地方法栈,可以通过他们服务的对象不同来说。
    java栈是服务于虚拟机使用的java方法,而本地方法栈是服务于虚拟机使用到的本地(native)方法。
  • 4.java堆和方法区
    java堆和方法区都归属于虚拟机的堆。这里二者比较着说,更容易理解记忆!二者只是根据存储对象不同进行的认为概念上的划分,并不存在内存上的物理隔离。java堆存储的是对象实例即下图中的中间实例数据部分,方法区存储的是对象的类信息,常量和静态变量。即下图中的对象头部分和部分实例数据部分。这里我们可以通过一个图来形象的说。
    下图是一个Object对象。
    《深入理解java虚拟机》的内存模型个人理解

而GC回收的管理区域就是堆,包括java堆和方法区。java堆是虚拟机管理的内存最大的一块区域,也是被所有线程共享的区域。这句话怎么理解呢?我们可以这么想,我们controller层调用service层,如果这个service能够同时执行几个线程,这几个线程又公用一个对象资源,这个对象肯定放在java堆上,那就在这几个线程中肯定是要共享的。所以这个对象在堆中是被所有线程共享的,那堆就是线程共享的区域。
按照GC对对象按照年龄的划分:java堆中存储着新生代和年老代(Eden,Survivor),方法区中存储着永久代(perm)。