JVM 内存模型(Java运行时内存分配策略)

在这里插入图片描述

在这里插入图片描述

  • 栈帧,Java虚拟机栈会为每一个即将执行的方法创建一个叫做“栈帧”的区域,该区域用来存储该方法运行时需要的一些信息,包括:局部变量表、操作数栈、动态链接、方法返回地址等。比如我们方法执行过程中需要创建变量时,就会将局部变量插入到局部变量表中,局部变量的运算、传递等在操作数栈中进行,当方法执行结束后,这个方法对应的栈帧将出栈,并释放内存空间。
  • 栈中会发生的两种异常,StackOverFlowError和OutOfMemoryError
    StackOverFlowError表示当前线程申请的栈超过了事先定好的栈的最大深度,但内存空间可能还有很多。
    OutOfMemoryError是指当线程申请栈时发现栈内存不足。
  • 递归引起的栈异常
    • 每个方法在调用自己的时候还没有退出,导致内存不释放,多了容易引起OutOfMemoryError
    • 每进入一次递归,就会增加一层栈帧,方法返回时清理当前栈帧,栈的大小不是无限的,所以递归过多容易StackOverFlowError
  • 栈内存是线程私有的,每个线程都有自己的一个栈内存区域
  • 局部变量表中存放基本类型的变量,对象的引用(指向堆内存中的地址)
    在这里插入图片描述

本地方法栈

  • 和虚拟机栈类似,不过区别是专门提供给Native方法用的。

堆(线程间共享)

在这里插入图片描述

  • new出来的对象和数组
  • 分为年轻代和老年代,老年代占2/3,年轻代占1/3
  • 年轻代有分为Eden、from、to三个区分别占用大小8/10、1/10、1/10
  • 新new出来的对象在Eden区,当Eden满后,触发minorGC进行回收,清理无效对象(没有被引用的对象,例如当前栈帧执行完毕被回收到,对应的堆中的局部变量便不再被引用,成为无效对象),被留下来的对象进入Survivor区(包含from、to区),from区满后执行minorGC,被保留下的对象进入to区,然后to区域触发GC进入from,循环往复,每次GC后对象的年龄+1,直到年龄大于15后进入老年代,老年代满后触发fullGC,总体做一个垃圾回收,如果无法回收出内存则触发OutOfMemoryError

方法区(线程间共享)

  • 存放常量、静态变量、类信息(程序编译时已经分配好,在整个程序运行期间都会存在)
  • 直接存放在计算机物理内存中,不在jvm虚拟机内存中
    在这里插入图片描述

程序计数器

  • 程序计数器是一个比较小的内存空间,用来记录当前线程正在执行的那一条字节码指令的地址。如果当前线程正在执行的是本地方法,那么此时程序计数器为空。程序计数器有两个作用,1、字节码解释器通过改变程序计数器来一次读取指令,从而实现代码的流程控制,比如我们常见的顺序、循环、选择、异常处理等。2、在多线程的情况下,程序计数器用来记录当前线程执行的位置,当线程切换回来的时候仍然可以知道该线程上次执行到了哪里。而且程序计数器是唯一一个不会出现OutOfMeroryError的内存区域。

参考资料

猜你喜欢

转载自blog.csdn.net/yu540135101/article/details/113104927