JVM学习(二)-- JVM内存布局

JVM内存布局


JVM内存布局规定了Java在运行过程中内存申请、分配和管理的策略,保证了JVM的高效稳定运行,其经典内存布局如下图所示

在这里插入图片描述

程序计数器

  • 线程私有
  • 用于存放执行指令的偏移量和行号指示器等,线程执行或恢复都需依赖程序计数器
  • 用以完成分支、循环、跳转、异常处理、线程恢复等基础功能。不会发生OOM错误

本地方法栈

  • 线程私有
  • 登记native方法,在Execution Engine 执行时加载本地方法库。
  • 本地方法可通过JNI(Java Native Interface)来访问虚拟机运行时的数据区,具有和JVM相同的能力和权限
  • 内存不足时,本地方法栈会抛出native heap OutOfMemory
  • JNI使Java深度使用操作系统的特性功能,可调用非Java代码

虚拟机栈

  • 线程私有
  • 描述Java方法执行的内存区域,每个方法从开始调用到执行完成的过程,就是栈帧从入栈到出栈的过程
  • 在活动线程中,只有位于栈顶的帧才是有效的,称为当前帧。正在执行的方法称为当前方法,栈帧是方法运行的基本结构
  • 在执行引擎运行时,所有指令都只能针对当前栈帧操作
  • 当创建的栈帧超过了栈的深度,导致栈溢出,会发生StackOverflowError,通常出现在递归方法中
  • 栈帧主要包括局部变量表操作栈动态连接方法返回地址
    • **局部变量表:**存储方法参数和局部变量
    • 操作栈: 记录出入栈操作
    • 动态连接:每个栈帧中包含一个在常量池中对当前方法的引用,用于支持方法调用过程的动态连接
    • 方法返回地址:方法退出有两种情况:(1)正常退出,即执行到任何方法的返回字段;(2)异常退出;无论何种退出,都将返回至方法当前被调用的位置,即弹出当前栈帧。退出有三种方式:(1)返回值压入上层调用栈帧;(2)异常信息抛给能处理的栈帧;(3)PC计数器指向方法调用后的下一条指令

堆区

  • 线程共享
  • 存储着几乎所有的实例对象,由垃圾收集器自动回收
  • OOM的主要发源地, OOM原因有二:
    • JVM堆内存设置不够,可通过-Xms -Xmx设置
    • 程序创建了大量大对象,并长时间不能被垃圾收集器回收
  • 占用空间所有内存区域中最大
  • 堆内存大小可固定,也可动态调整,如-Xms256M -Xmx1024M, 分别设置最小堆容量与最大堆容量,一般为避免GC后调整堆大小带来的额外压力,设置成固定大小
  • 堆 = 新生代+老年代 大小比例为: 新生代:老年代 = 1:2
    • 新生代 = Eden区+Survivor 0 +Survivor 1, 大小比例为:Eden:Survivor 0:Survivior 1 = 8:1:1
    • 绝大部分对象在Eden区生成,当Eden满后,触发YGC,回收没有被引用的对象,依然存活的对象移送至Survivor区
    • Survivor区分为S0和S1两块内存空间,YGC每次将存活的对象复制到未使用的空间,然后将当前正在使用的空间完全清除,并交换两块空间的使用状态
    • 若YGC移送的对象大于Survivor区容量,则直接移送至老年代
    • 每次YGC对象的计数器都会+1,当达到默认值15时,从新生代晋升至老年代,阈值可通过-XX:MaxTenuringThreshold配置
    • 若老年代也无法放心,则触发FGC,依然无法放下,则OOM,打印OOM异常堆内信息可通过设置运行参数-XX:+HeapDumpOnOutOfMemoryError输出

堆区对象分配与GC简要流程图如下:
在这里插入图片描述

元空间

  • 线程共享
  • 区别于JDK8之前的永久代,元空间在本地内存中分配
  • 存储类元信息,字段,静态属性,方法,常量等
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java内存模型(Java Memory Model,JMM)定义了Java程序在多线程环境下的内存访问规则。它规定了线程如何和主内存、本地内存以及其他线程进行通信。 JVM内存模型是指Java虚拟机(Java Virtual Machine,JVM)在执行Java程序时的内存布局和管理方式。JVM内存模型包括了堆内存、栈内存、方法区、直接内存等。 在Java内存模型中,主要有以下几个概念: 1. 主内存:所有线程共享的内存区域,包含了实例字段、静态字段以及数组元素。 2. 工作内存:每个线程独立的内存区域,包含了该线程使用的变量副本或者缓存。 3. 内存间的交互操作:线程之间通过读写主内存来进行通信。 4. 原子性、可见性和有序性:JMM保证了原子性(对基本类型的读写操作具有原子性)、可见性(一个线程对主内存的修改对其他线程是可见的)和有序性(在一个线程中,按照程序顺序执行)。 JVM内存模型主要包括以下几个部分: 1. 堆内存:用于存储对象实例,由垃圾回收器进行管理。 2. 栈内存:用于存储方法的局部变量和方法调用的信息。每个线程都有自己的栈内存。 3. 方法区:用于存储类的信息、常量、静态变量等。 4. 直接内存:在堆外分配内存,不受JVM管理,由操作系统进行管理。 需要注意的是,JVM内存模型是具体实现的一种规范,可以根据不同的JVM厂商进行优化和调整。而Java内存模型是Java语言规范中定义的多线程内存访问规则,对于不同的JVM实现都是一样的。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值