系统相关
首页 > 系统相关> > JVM 内存模型,java全套视频教程

JVM 内存模型,java全套视频教程

作者:互联网

2.1.3. 程序计数器的特点

  1. 是一块较小的存储
【一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义】

浏览器打开:qq.cn.hn/FTf 免费领取

空间

  1. 线程私有。每条线程都有一个程序计数器。

  2. 是唯一一个不会出现OutOfMemoryError的内存区域。

  3. 生命周期随着线程的创建而创建,随着线程的结束而死亡。

2.2 虚拟机栈

虚拟机栈,生命周期与线程相同,是Java方法执行的内存模型。每个方法(不包含native方法)执行的同时都会创建一个栈帧结构,方法执行过程,对应着虚拟机栈的入栈到出栈的过程。

特点

  1. 局部变量表的创建是在方法被执行的时候,随着栈帧的创建而创建。而且,局部变量表的大小在编译时期就确定下来了,在创建的时候只需分配事先规定好的大小即可。此外,在方法运行的过程中局部变量表的大小是不会发生改变的。

  2. Java虚拟机栈会出现两种异常:StackOverFlowError和OutOfMemoryError。

a) StackOverFlowError:

若Java虚拟机栈的内存大小不允许动态扩展,那么当线程请求栈的深度超过当前Java虚拟机栈的最大深度的时候,就抛出StackOverFlowError异常。

b) OutOfMemoryError:

若Java虚拟机栈的内存大小允许动态扩展,且当线程请求栈时内存用完了,无法再动态扩展了,此时抛出OutOfMemoryError异常。

  1. Java虚拟机栈也是线程私有的,每个线程都有各自的Java虚拟机栈,而且随着线程的创建而创建,随着线程的死亡而死亡。

注:StackOverFlowError和OutOfMemoryError的异同?

StackOverFlowError表示当前线程申请的栈超过了事先定好的栈的最大深度,但内存空间可能还有很多。

而OutOfMemoryError是指当线程申请栈时发现栈已经满了,而且内存也全都用光了。

栈帧(Stack Frame)结构

栈帧是用于支持虚拟机进行方法执行的数据结构,是属性运行时数据区的虚拟机站的栈元素。见上图, 栈帧包括:

  1. 局部变量表 (locals大小,编译期确定),一组变量存储空间, 容量以slot为最小单位。

  2. 操作栈(stack大小,编译期确定),操作栈元素的数据类型必须与字节码指令序列严格匹配

  3. 动态连接, 指向运行时常量池中该栈帧所属方法的引用,为了 动态连接使用。

  1. 方法返回地址
  1. 额外附加信息,虚拟机规范没有明确规定,由具体虚拟机实现。

注意:人们常说,Java的内存空间分为“栈”和“堆”,栈中存放局部变量,堆中存放对象。

这句话不完全正确!这里的“堆”可以这么理解,但这里的“栈”只代表了Java虚拟机栈中的局部变量表部分。真正的Java虚拟机栈是由一个个栈帧组成,而每个栈帧中都拥有:局部变量表、操作数栈、动态链接、方法出口信息。

异常(Exception)

Java虚拟机规范规定该区域有两种异常:

2.3 本地方法栈

本地方法栈和Java虚拟机栈实现的功能类似,只不过本地方法区是本地方法运行的内存模型。

本地方法被执行的时候,在本地方法栈也会创建一个栈帧,用于存放该本地方法的局部变量表、操作数栈、动态链接、出口信息。

方法执行完毕后相应的栈帧也会出栈并释放内存空间。

异常(Exception):Java虚拟机规范规定该区域可抛出StackOverFlowError和OutOfMemoryError。

2.4 Java堆

Java堆,是Java虚拟机管理的最大的一块内存,也是GC的主战场,里面存放的是几乎所有的对象实例和数组数据。整个Java虚拟机只有一个堆,所有的线程都访问同一个堆。而程序计数器、Java虚拟机栈、本地方法栈都是一个线程对应一个的。

不同的区域存放具有不同生命周期的对象。这样可以根据不同的区域使用不同的垃圾回收算法。这样划分的好处是为了更快的回收内存;

对象创建的过程是在堆上分配着实例对象,那么对象实例的具体结构如下:

java_object

对于填充数据不是一定存在的,仅仅是为了字节对齐。HotSpot VM的自动内存管理要求对象起始地址必须是8字节的整数倍。对象头本身是8的倍数,当对象的实例数据不是8的倍数,便需要填充数据来保证8字节的对齐。该功能类似于高速缓存行的对齐。

另外,关于在堆上内存分配是并发进行的,虚拟机采用CAS加失败重试保证原子操作,或者是采用每个线程预先分配TLAB内存.

异常(Exception):Java虚拟机规范规定该区域可抛出OutOfMemoryError。

2.5 方法区

方法区主要存放的是已被虚拟机加载的类信息、常量、静态变量、编译器编译后的代码等数据。GC在该区域出现的比较少。

特点

  1. 线程共享

方法区是堆的一个逻辑部分,因此和堆一样,都是线程共享的。整个虚拟机中只有一个方法区。

  1. 永久代

方法区中的信息一般需要长期存在,而且它又是堆的逻辑分区,因此用堆的划分方法,我们把方法区称为老年代。

  1. 内存回收效率低

方法区中的信息一般需要长期存在,回收一遍内存之后可能只有少量信息无效。

对方法区的内存回收的主要目标是:对常量池的回收 和 对类型的卸载。

  1. Java虚拟机规范对方法区的要求比较宽松。

和堆一样,允许固定大小,也允许可扩展的大小,还允许不实现垃圾回收。

异常(Exception):Java虚拟机规范规定该区域可抛出OutOfMemoryError。

2.6 运行时常量池

运行时常量池也是方法区的一部分,用于存放编译器生成的各种字面量和符号引用。运行时常量池除了编译期产生的Class文件的常量池,还可以在运行期间,将新的常量加入常量池,比较常见的是String类的intern()方法。

大小,还允许不实现垃圾回收。

异常(Exception):Java虚拟机规范规定该区域可抛出OutOfMemoryError。

2.6 运行时常量池

运行时常量池也是方法区的一部分,用于存放编译器生成的各种字面量和符号引用。运行时常量池除了编译期产生的Class文件的常量池,还可以在运行期间,将新的常量加入常量池,比较常见的是String类的intern()方法。

标签:Java,虚拟机,线程,内存,JVM,OutOfMemoryError,java,方法,视频教程
来源: https://blog.csdn.net/m0_63174529/article/details/121225392