2019-2-25 java内存模型(JAVA Memory Model)笔记整理

有时间了,还是把笔记本上的东西,整理到博客上,有借鉴别人的,但这块的知识是固定的,自己吸收最重要;

Java虚拟机(JVM)在运行过程中,会将内存划分几块不同的数据区域,我个人理解为逻辑区域划分:

寄存器/程序计数器:一小块内存空间,保存当前线程正在执行的字节码的行号指示器,由于程序执行并非线性的,当多个线程交叉执行时,某个被中断的线程执行到哪块了需要被标识和保存,以便它在恢复执行时,可以继续到被中断的位置执行;每个线程都需要有一个独立的程序计数器,并且之间互不影响,独立存储,所以该区域为“线程私有”的内存;

如果线程执行的是一个java方法,计数器记录的是正在执行的虚拟机字节码指令 的地址,如果执行的是native方法,则计数器值为空,此区域是jvm规范中,唯一没有规定任何oom情况的区域;

虚拟机栈(java stack):线程私有的,生命周期与线程相同。虚拟机栈描述的是Java方法执行的内存模型,每创建一个线程的时候,对应会创建一个Java栈,每个栈中会包含多个栈帧;栈帧是与方法关联的,每调用一个方法,就会创建一个栈帧(压栈),栈帧中包含了局部变量,操作栈,动态链接,方法出口等信息。每当方法执行完成,该栈帧就会弹出栈帧的元素作为这个方法的返回值,并且清除这个栈帧(弹栈),Java栈遵循先进先出原则,即栈顶是当前正在执行的方法栈。pc寄存器也会指向该地址。该区域为“线程私有的”。

Java虚拟机规范中,规定了该区域的两种异常情况:如果线程请求的栈深度大于虚拟机所允许的最大深度,抛出stackoverflow异常;

如果虚拟机可以动态拓展,当拓展时无法申请到足够的内存,则抛出outofmemory异常。(可以设置栈的大小 -Xss 直接决定函数调用的可达深度)

堆区(heap):jvm内存中区域最大,被所有Java线程共享的区域,线程不安全,在jvm启动时创建;所有对象实例均在该区域存储分配,是gc发生的主要区域。gc基本采用分代收集算法,所以堆内还分为新生代(Eden、from survivor、to sruvivor)、老年代;

方法区:存储要加载的类的信息、类中的静态常量、类中final类型的常量、类中的 字段和方法信息;该区域为Java线程共享的。存储相对稳定,只会在一定条件下发生gc,当使用的内存超过其允许的大小时,抛出oom异常。方法区也是堆的一部分,即堆中的永久代。可通过参数来设置大小:-XX:permsize 初始值,-XX:maxPermSize 最大值;

本地方法栈-Native Method Stack:本地方法栈和Java栈所发挥的作用非常相似,区别不过是Java栈为JVM执行Java方法服务,而本地方法栈为JVM执行Native方法服务。本地方法栈也会抛出StackOverflowError和OutOfMemoryError异常。

 

待续。。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值