深入理解java虚拟机
运行时内存区域
总览
详细介绍
程序计数器
程序计数器是一块较小的内存空间,它可以看做当前线程所执行的字节码行号记录器。
Java虚拟机栈
Java虚拟机栈是线程私有的,他的生命周期与线程相同。虚拟机栈描述的是Java方法执行的内存模型:每个方案执行时,都会同步创建一个栈帧 用于存储局部变量、操作数栈、动态链接、方法出口等信息。每个方法被调用直至执行完毕的过程,就对应着一个栈帧 从虚拟机栈入栈和出栈的过程。
本地方法栈
本地方法栈 和 Java虚拟机栈的作用类似,只是本地方法栈为本地方法(native)服务。
Java堆
Java堆是所有线程共享的内存区域,在虚拟机启动时创建。此内存的唯一作用就是存放对象实例,Java中“几乎所有”对象都在这里分配内存。
方法区
方法区 和 Java堆一样,是各个线程共享的内存区域,他用于存储虚拟机加载的类型信息、常量、静态常量、及时编译器编译后的代码缓存等数据。
HotSpot虚拟机对象揭秘
对象创建
对象的内存布局
在HotSpot虚拟机中,对象在堆内存中存储布局可以划分为三个部分:对象头(Header)、示例数据(Instance Data)和对齐填充(Padding)。
对象头有两类信息。第一种是存储对象自身运行时数据,如hash值,GC分代年龄,锁状态。 第二种是类型指针,指针指向其类对象。
对象的方位定位
| 通过句柄访问对象 | 通过直接指针访问对象 | |
|---|---|---|
| 优点 | 对象发生移动时,只需要修改句柄中指针就好,修改性能高 | 访问效率高 |
| 缺点 | 访问效率低 | 对象发生移动时,需要修改所有应用该对象的reference |
垃圾回收策略与内存分配策略
实现一个垃圾回收期,主要考虑3个问题。
- 哪些内存需要回收
- 什么时候回收
- 如何回收
如何判断是否需要回收
引用计数法
实现:
在对象中添加一个引用计数器,每当有一个地方引用他,计数器数值就加一;引用失效时,计数器就减一。
缺点:循环引用的对象无法被回收。
可达性分析
实现:
通过一系列“GC Roots”的根对象作为起始节点集,从这些节点开始,根据引用链开始向下搜索,搜索过程所走的路径成为“引用链”,如果某个对象到GC Roots之间没有“引用链”,说明这个对象不可达,可以判定为可回收对象。
GC Roots有哪些:
- Java虚拟机栈中应用的对象,例如:参数、局部变量
- 类静态变量中引用的对象。
- 同步锁持有的对象
- …