0%

运行时数据区.md

[TOC]

Java 的运行时数据区介绍: 程序计数器、虚拟机栈、本地方法栈、方法区、堆等。

运行时数据区

程序计数器

线程私有,直接划分在CPU上。用于存储线程执行的字节码指令地址(若为native方法,则指向null)

虚拟机栈

线程私有,存储许多栈帧,每个栈帧包含有局部变量表、操作数栈、动态连接、方法出口等。

该处可能会发生2项异常:StackOverflowError和OutOfMemoryError。

具体参考深入理解JAVA虚拟机第8章。

img

本地方法栈

与虚拟机栈类似。

java堆

线程共享,保存所有对象的实例和数组。

如上图,各区域占比:

  • Edem : Survivor from : Survivor to = 8 : 1 : 1
  • Young : Old = 1 : 2

方法区

线程共享,存储已被加载的类信息、常量、静态变量、即时编译器编译后的代码等数据

持久带和方法区:方法区物理上存在于堆里,而且是在堆的持久代里面;但在逻辑上,方法区和堆是独立的。在jdk1.8版本后,持久区被移除,改为metaspace区

运行时常量池

运行时常量池是方法区的一部分。当类被加载时,class文件的常量池会被加载到“运行时常量池”。
另一个特性是具备动态性。(String.intern())

对象内存布局

  • 对象头:存储对象自身的运行时数据,如hash值、GC、锁等;类型指针,确定是哪个类的实例
  • 实例数据:对象真正的有效数据
  • 对齐填充:保证对象的大小为8字节的倍数。

对象访问定位

  1. 句柄定位
  2. 直接指针:sun HotSpot使用的方法。

OutOfMemoryError

  1. java堆溢出:对象实例创建过多。
  2. 虚拟机栈和本地方法栈溢出:递归调用。
  3. 方法区和运行时常量池溢出
  4. 直接内存溢出

参考资料:

JVM 堆内存设置原理