JVM学习笔记——1.Java内存区域与内存溢出异常

1.1运行时数据区

Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域,他们有各自的用途以及创建销毁时间,一些区域随着虚拟机进程的启动一直存在,有一些则是依赖用户线程的建立和销毁。
其中云形状的为线程共享数据区,其他为线程隔离数据区
其中云形状的为线程共享数据区,其他为线程隔离数据区

1.1.1 程序计数器

内存空间较小,当前线程所执行字节码的行号指示器,分支、循环、跳转、异常处理、线程恢复等基础功能都要依赖这个计数器。
每条线程私有,如果线程执行是一个Java方法计数器记录的是正在执行的虚拟机字节码指令地址;如果是本地方法,则计数器值为空,该区域是唯一一个没有OutOfMemoryError的区域

1.1.2 Java虚拟机栈

线程私有,每个方法被执行,Java虚拟机都会同步创建一个栈帧用于存储局部变量表、操作数表、动态连接、方法出口等信息。每个方法被调用直至执行完毕的过程,就对应着一个栈帧在虚拟机栈从入栈到出栈的过程。
局部变量表存放基本数据类型,这些数据类型的存储空间以局部变量槽来表示,long和double占两个变量槽。
如果线程请求的栈深度大于虚拟机允许的栈深度抛出StackOverflowError异常;如果Java虚拟机栈容量可以动态扩展,无法申请到足够内存时抛出OutOfMemoryError异常

1.1.3 本地方法栈

与虚拟机栈类似只不过,本地方法栈服务于本地方法

1.1.4 Java堆

内存中最大,线程共享,目的是存放对象的实例,所有的对象实例以及数组都应当在堆上分配
所有线程共享的Java堆可以划分出多个线程私有的缓冲区,主流的Java虚拟机都是按照可扩展来实现的(通过-Xmx和-Xms参数来设定),堆无法扩展时抛出OutOfMemoryError异常

1.1.5 方法区

线程共享,用于存储已经被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等信息,不需要连续的内存,可选择固定大小和可扩展,还可以选择不实现垃圾收集。
当方法区无法满足新的内存分配需求时,抛出OutOfMemoryError异常

1.1.6 运行时常量池

是方法区的一部分,类信息中的常量池表存放在这里。当常量池无法再申请到内存时抛出OutOfMemoryError异常

1.1.7 直接内存

直接内存不是运行时数据区的一部分,目的是避免在Java堆和Native中来回复制数据,会出现OutOfMemoryError异常

1.2 HotSpot虚拟机对象探秘

1.2.1 对象创建(普通Java对象)

  1. 检查这个指令的参数是否能在常量池中定位到一个类的引用,并且检查这个类是否已被加载、解析和初始化过,如果没有则先进行类加载过程。
  2. 为对象分配内存,按照堆的内存是否规整,分为‘’指针碰撞法‘’和‘’空闲列表法‘’,堆是否规整取决于使用的垃圾收集器是否有压缩功能。
    除划分空间外还有多线程并发问题,指针可能同时被多个线程修改,两种解决方案,一种是CAS加上失败重试,另一种每个线程预先分配一小块内存,称为本地线程缓冲区,线程分配对象优先在缓冲区分配,简称TLAB法,可以通过-XX:+/-UseTLAB参数设定。
  3. 初始化内存空间(不包括对象头)为0值,保证实例字段不赋值也能使用。
  4. 设置对象头信息,例如哈希码,GC分代信息
  5. 执行Class文件中的方法,进行初始化

1.2.2 对象的内存布局

对象在堆中分三个部分:对象头、实例数据和对齐填充。

  1. 对象头包括两类信息,一类用于存储对象自身的运行时数据,例如:哈希码、GC分代信息等,成为‘’Mark Word‘’,它被设计成有着动态定义的数据结构,结构如下
    在这里插入图片描述

另一类信息是类型指针,虚拟机通过这个指针来判断该对象是哪个类的实例,但并不是所有的对象数据都有类型指针。

  1. 实例数据部分是对象真正的有效信息
  2. 对齐填充起着占位符的作用,对象必须是8字节的整数倍

1.2.3 对象访问定位

访问对象主流有两种方式,使用句柄和直接指针

  • 如果使用句柄访问,堆中划分出一块内存作为句柄池,reference中存储的是对象的句柄地址,句柄中包含对象实例数据与类型数据各自的地址信息。
    在这里插入图片描述
  • 如果使用直接指针访问,reference中存储的直接是对象地址,如果只是访问对象本身,就不需要一次间接访问的开销
    在这里插入图片描述
    这两种各有优势,句柄访问最大的好处是reference中存储的是稳定的句柄地址,在对象被移动时只会改变句柄中的实例数据指针;而使用直接访问的好处是速度更快,它节省了一次指针定位的时间开销
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值