JVM运行时数据区学习笔记

1 程序计数器
  1. 很小的一块内存区域,可以看做是当前线程执行的字节码的行号指示器,字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令
  2. 分支、循环、跳转、异常处理、线程恢复等基础功能都是依赖程序计数器来完成的。所以程序计数器记录的是当前执行的字节码指令地址,当执行完成之后再跳转到下一行,毕竟比如说分支执行完成之前是不知道下一条应该是哪一行的。
  3. 因为多线程切换后要恢复到正确的执行位置,所以每条线程都需要有一个独立的行号计数器
  4. 程序计数器也是虚拟机规范中唯一没有指明OutOfMemoryError的区域
2 Java虚拟机栈
  1. 主要描述的是Java方法执行的内存模型,每个方法执行时都会创建一个栈帧,用于储存局部变量表、操作数栈、动态练级诶、方法的返回地址、还有一些其他信息(可以没有)。每个方法的的调用和返回,都对应着一个栈帧的入栈和出栈
  2. 局部变量表存放了编译期可知的各种基本数据类型(8种)以及对象引用类型和returnAddress类型(指向了一条字节码指令的地址)
  3. 比较特殊的是double和long类型的数据会占据两个slot空间,其余所有都只会占用一个空间,局部变量表的内存空间是在编译期完成分配的,所有栈帧中的局部变量空间是完全确定的
  4. 可能会出现两种异常,若线程请求深度大于虚拟机栈所运行的最大深度,会抛出StackOverflowError异常。若虚拟机栈在扩展时无法申请到足够的空间,会抛出OutOfMemoryError异常
  5. 操作数栈的内存空间也是确定的,记录方法中的计算时入栈和出栈的操作
3 本地方法栈

与Java虚拟机栈相对应,Java虚拟机栈是执行Java方法的,而本地方法栈是执行native方法的,也同样存在两种异常情况

!!!以上程序计数器、Java虚拟机栈、本地方法栈都是线程私有的,每一个线程都对应有这三个区域,并且没有垃圾回收

4 Java堆
  1. 是Java虚拟机管理内存中最大的一块内存区域,默认起始内存为1/64的物理电脑内存,最大内存为1/4。所有对象的实例以及数组都要在堆上分配(目前是比较绝对的,但是随着虚拟机技术的发展,栈上分配局部变量内存也许也是可以考虑的,可以有效减少垃圾回收)
  2. 从内存回收的角度,Java堆可以分为新生代和老年代,比例大概默认为1:2,新生代又可以分为Eden空间、Form Survivor空间、To Survivor空间,大概比例默认为8:1:1。绝大多数对象的分配都是在Eden空间的,然后随着内存的回收会来到Form或者To区,这两个空间不会同时储存对象的,最后年龄大的对象会去到老年代中。若是大对象可以直接在老年代中分配。
  3. 从内存分配的角度来说,Java堆可以分出多个线程私有的分配缓冲区(TLAB),因为线程并发的情况下,对于堆上内存分配是可能出现错误的,所以每次操作都需要加锁,而削弱了性能。若每个线程都有部分自己私有的分配区域,先在这部分内存上分配便可以加快效率。
  4. 内存的进一步划分的目的是为了更好地回收内存,或者是为了更快的分配内存
  5. Java堆是可以处于物理上不连续的内存空间,只需要逻辑上连续即可,若堆上没有足够的空间完成对象分配时,且无法再扩展时,会抛出OutOfMemoryError异常
5 方法区
  1. 储存已被虚拟机加载的类信息、常亮、静态变量、即时编译器编译后的代码等数据,HotSpot虚拟机是用永久代去实现的方法区,但较容易出现内存溢出的问题。Java7中把字符串常量池移除到了堆空间,Java8中会用元空间代替永久代。
  2. 方法区是可以不实现垃圾收集的,但出现内存不足情况依然会抛出OutOfMemoryError异常的

主要内容都是来源于学习《深入理解Java虚拟机》所勾画的笔记

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值