Java内存区域与内存溢出异常 JVM笔记1

目录

运行时数据区域

程序计数器

虚拟机栈

本地方法栈

方法区

直接内存

对象的内存布局

对象头

实例数据

对齐填充

对象的访问定位


运行时数据区域

JAVA虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域。

程序计数器

  • 一块较小的内存空间,可以看作当前线程所执行的字节码的行号指示器
  • 通过改变这个计数器的值来选取下一条需要执行的字节码指令。
  • 每条线程都需要一个独立的程序计数器各条线程之间互不影响,独立存储,我们称这类内存区域为线程私有的内存。

虚拟机栈

  • 也是线程私有的,生命周期与线程相同。
  • 用来描述Java执行的内存模型(局部变量表,操作数栈,动态链接,方法出口等)
  • 如果线程请求的栈深度大于虚拟机所允许的深度,抛出StackOverflowError异常
  • 如果虚拟机栈可以动态扩展,扩展时无法申请到足够的内存,就会抛出OutOfMemoryError异常

本地方法栈

  • 线程私有
  • 与虚拟机栈作用类似,不过虚拟机栈为虚拟机执行Java方法服务,而本地方法栈为虚拟机使用到的Native方法服务
  • 也会抛出StackOverflowError和OutOfMemoryError异常

  • 线程共享
  • Java虚拟机所管理内存最大的一块,在虚拟机启动时创建。
  • 用于存储对象实例,几乎所有对象实例都在这里分配内存。
  • 是垃圾收集器管理的主要区域
  • 如果堆中没有内存完成实例分配,并且堆也无法扩展时,将会抛出OutOfMemoryError异常

方法区

  • 线程共享
  • 用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据
  • 很少出现垃圾回收行为
  • 常量池时方法区的一部分,Class文件除了又类的版本、字段、方法、接口等描述信息外,还有一项信息是常量池,用于存放编译器生成的各种字面量和符号引用,这部分内容在类加载后进入方法区的运行时常量池中存放。常量池具有动态性,运行期间也可能将新的常量放入池中,比如String类的intern()方法
  • 无法满足内存分配需求时,将抛出OutOfMemoryError异常

直接内存

  • 即本机的内存,不是虚拟机运行时数据区的一部分,但是经常用到。
  • 也可能导致OutOfMemoryError异常,比如为虚拟机分配的内存大于物理内存限制。

对象的内存布局

在HotSpot虚拟机中,对象在内存中的存储的布局可以分为3块区域:对象头(Header)、实例数据(Instance Data)和对其填充(Padding)。

对象头

HotSpot的对象头包括两部分信息。
第一部分:

  • 存储对象自身的运行时数据。哈希码、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等。
  • 长度在32位和64位虚拟机中(未开启压缩指针)中分别为32bit和64bit,官方称它为“Mark Word”。

第二部分

  • 对象头另外一部分时类型指针,即对象指向它的类元数据的指针,虚拟机通过这个指针来确定对象是哪个类的实例
  • 若对象是数组,那么在对象头中还必须有一块用于记录数组长度的数据。

实例数据

  • 是对象真正存储的有效信息,也是程序代码中所定义的各种类型的字段内容。
  • HotSpot虚拟机默认的分配策略为longs/doubles,ints,shorts/chars,bytes/booleans,oops(Ordinary Object Pointers),相同宽度的字段总是被分配在一起。

对齐填充

  • 并不是必然存在的,也没有特别含义。
  • 起到占位符的作用。

对象的访问定位

建立对象是为了使用对象,我们的Java程序主要通过栈上的reference数据来操作堆上的具体对象。由于reference类型在java虚拟机规范中只规定了一个指向对象的引用,并没有定义这个引用应该通过什么样的方式区定位、访问堆中对象的具体位置,所以对象访问方法方式也是取决于虚拟机实现而定的。目前主流的访问方式为句柄直接指针两种。

  • 若是使用句柄访问,Java堆中会划出一块内存作为句柄池,reference中存储的就是对象的句柄地址,句柄中包含对象实例数据(在Java堆)与类型数据(在方法区)各自的具体地址信息
    优点:在对象被移动时只会改变句柄中的实例数据指针,而reference本身不需要修改。
  • 若是使用直接指针访问,Java堆就必须考虑如何放置访问类型数据的相关信息,reference中存储的直接就是对象地址。
    优点:访问速度更快,节省一次指针定位时间。

猜你喜欢

转载自blog.csdn.net/zhuochuyu7096/article/details/84840995