【JVM】(1)Java内存区域

内存区域划分

1.Java8 之前

在这里插入图片描述
在这里插入图片描述

2.Java8及之后

在这里插入图片描述
在这里插入图片描述

各块区域解释

1. 程序计数器

  • 程序计数器(Program Counter Register)是一块较小的内存空间,它可以看作是当前线程所执行的字节码行号指示器
  • 字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,它是程序控制流的指示器,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。
  • 如果线程正在执行的是一个Java方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址;如果正在执行的是本地(Native)方法,这个计数器值则应为
  • 该区域是唯一不会发生OutOfMemory的区域。

2. Java虚拟机栈

  • 每个Java方法被执行的时候,Java虚拟机都会同步创建一个栈帧(Stack Frame)用于存储局部变量表、操作数栈、动态连接、方法出口等信息。
  • Java虚拟机栈存放的就是一个个栈帧
  • 基本数据类型对象引用就储存在局部变量表中。
  • 如果线程请求的栈深度大于JVM设定的虚拟机栈的最大深度,那么就会产生StackOverflow错误。
  • HotSpot虚拟机不允许栈容量扩展,因此不会引发OutOfMemory错误

3. 本地方法栈

  • 与Java虚拟机栈类似,区别是本地方法栈用于执行Native方法,Java虚拟机栈用于执行Java方法。
  • HotSpot虚拟机将Java虚拟机栈与本地方法栈合并。

4.

  • 内存区域中最大的一块,线程共享
  • 存放对象实例数组
  • 垃圾收集器工作的区域

思考:对象的成员变量储存在哪里?

对象的成员变量都储存在堆上,只有进入方法时,局部变量会存放在栈上。
也就是说基本数据类型、引用类型存在于堆和栈上都可以。

5. 方法区

  • 储存Class信息常量静态变量
  • Java8之前方法区位于中,Java8及之后,方法区被取消,使用位于直接内存的元空间代替方法区。
  • Java8之前,HotSpot虚拟机定义永久代作为JVM方法区的实现。
  • 方法区容量不够时会产生OutOfMemory错误。

6. 运行时常量池

  • 方法区的一部分,储存字面量和符号引用
  • 字面量包括:文本字符串基本数据类型的值final常量值

7. 直接内存

  • 即实际机器内存,Native函数库中提供了直接分配堆外内存的接口
  • 这部分内存也可能出现OutOfMemory错误。

例子

//待完善:使用jmap等工具监控内存使用

StackOverflow

  • 栈溢出定义
    如果线程请求分配的栈容量超过java虚拟机栈允许的最大容量的时候,java虚拟机将抛出一个StackOverFlowError异常。
  • 造成栈溢出的情况
  1. 方法递归调用过深
  2. 定义了大量的本地变量,增大此方法帧中本地变量表的长度。
  • JVM调整栈容量的命令
    -Xss

OutOfMemory

  • 堆溢出
    通过设置-Xmx-Xms调整堆的最大最小值
  • 方法区溢出
    Java8之前方法区在堆上,可以设置-XX:PermSize-XX:MaxPermSize调整永久代的大小,Java8及之后,可以设置-XX:MaxMetaspaceSize-XX:MetaspaceSize调整元空间大小
  • 直接内存溢出
    可以通过-XX:MaxDirectMemorySize参数来指定,如果不去指定,则默认与Java堆最大值(由-Xmx指定)一致。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值