深入理解java虚拟机精华总结:jvm内存模型(运行时数据区域)、对象、OOM异常

以前读过好几遍《深入理解java虚拟机》这本书,最近又打算重读一遍,并且做一些笔记,把重点内容记录下来,所以想开一个精华总结的系列,记录里面书中的重点内容。

jvm内存模型

java虚拟机在执行Java程序的过程中会把它管理的内存划分为不同的区域,每个区域都有各自的用途、创建和销毁的时间。

在这里插入图片描述

  • 程序计数器:当前线程所执行的字节码的行号指示器,每条线程都需要有一个独立的程序计数器(线程私有),不会发生OOM。
  • 虚拟机栈:线程私有,每个方法被执行的时候,Java虚拟机都会同步创建一个栈帧用于存储局部变量表、操作数栈、动态连接、方法出口等信息,会抛出StackOverflowError和OutOfMemoryError异常。
  • 本地方法栈:与虚拟机栈相似,为本地方法的执行服务,会抛出StackOverflowError和OutOfMemoryError异常。
  • :线程共享,存放对象实例,大小可通过参数-Xmx和-Xms设定,会抛出OutOfMemoryError异常。
  • 方法区:线程共享,用于存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等数据。
  • 运行时常量池:方法区的一部分,用于存放在类加载后Class文件常量池表中的信息(各种字面量与符号引用)。
  • 直接内存:不是虚拟机运行时数据区的一部分,NIO使用Native函数库直接分配堆外内存,然后DirectByteBuffer对象作为这块内存的引用。

对象

对象的创建

在这里插入图片描述

对象创建过程

  1. new关键字。
  2. 判断类是否已经被加载、解析、初始化,如果没有,要先进行类加载。
  3. 为新生对象分配内存。内存划分的方式取决于内存是否绝对规整(看使用的垃圾收集器),如果内存规整则使用指针碰撞法进行内存分配,也就是指针向空闲方向挪动一段距离;如果内存不规整,则通过空闲列表法进行分配,也就是用一个列表记录内存空闲区域,分配内存时从中取出一块来分配。内存分配要保证线程安全,通过CAS或者TLAB(线程本地分配缓存)保证,TLAB就是线程的本地缓存区,先给一个线程分配一块固定大小的内存区域,然后该线程创建的对象在该本地缓存区中分配内存。
  4. 设置对象头,包括类元数据信息指针,hashcode等一些信息
  5. 执行构造函数

对象的内存布局

在这里插入图片描述

对象的内存布局划分为三个部分:对象头实例数据对齐填充

  • 对象头:存储Mark Word类型元数据指针,如果是数组则还有数组长度。Mark Word是对象自身的运行时数据(见上图表格),类型元数据指针指向该对象的类元数据信息。
  • 实例数据:存储对象的真实数据,也就是各种类型的字段。
  • 对齐填充:非必须,保证对象起始地址是8字节的整数倍。

对象的访问定位

两种访问方式:句柄访问直接指针访问

句柄访问方式:从堆中划出一块内存作为句柄池,reference指针存储句柄地址,需要两次寻址找到对象。

在这里插入图片描述

直接访问方式:reference指针直接指向对象实例,对象头中存储类型元数据的指针,速度快,节省一次寻址的开销。

在这里插入图片描述

OOM异常

在这里插入图片描述

Java堆溢出

java.lang.OutOfMemoryError: Java heap space

原因

  • 内存泄漏
  • 没有内存泄漏,堆内存太小

处理方法

  1. 过参数 -XX:+HeapDumpOnOutOf-MemoryError 让虚拟机在出现内存溢出异常的时候Dump出当前的内存堆转储快照。
  2. 通过内存映像分析工具对Dump出来的堆转储快照进行分析。
  3. 分清楚到底是出现了内存泄漏(Memory Leak)还是内存溢出(Memory Overflow)。
  4. 如果是内存泄漏,查看泄漏对象到GC Roots的引用链,找出产生内存泄漏的代码的具体位置。
  5. 如果不是内存泄漏,看是否还能调大堆参数(-Xmx与-Xms)的设置,减少其他对象的内存消耗。

栈溢出

java.lang.StackOverflowError

原因

  • -Xss 栈内存容量设置过小
  • 递归层数过大,压栈过深
  • 本地变量太多,栈帧太大

方法区溢出

java.lang.OutOfMemoryError: PermGen space

JDK 8以后,没有了永久代,改成在直接内存中的元空间,所以不会再出现。

原因

  • 运行时常量池溢出
  • 大量动态类(CGLib)
  • 大量JSP或动态产生JSP文件

直接内存溢出

java.lang.OutOfMemoryError

由直接内存导致的内存溢出,一个明显的特征是在Heap Dump文件中不会看见有什么明显的异常情况,如果内存溢出之后产生的Dump文件很小,而程序中又直接或间接使用了直接内存(典型的间接使用就是NIO),那就可以考虑重点检查一下直接内存方面的原因了。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值