JVM运行时数据区

参考资料:《深入理解Java虚拟机(第2版)》

 

概述

Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域,这些区域都有各自的用途。根据Java虚拟机规范(JavaSE 7版),Java虚拟机所管理的内存将会包括以下几个运行时数据区域:
在这里插入图片描述
 
 

程序计数器

一块较小的内存空间,可以被看作是当前线程所执行的字节码的行号指示器。字节码解释器通过改变它来选择下一条需要执行的字节码指令。
 
 

虚拟机栈

为虚拟机执行Java方法(也就是字节码)服务,生命周期与线程相同。Java方法执行时会创建一个栈帧,用于存储 局部变量表、操作数栈、动态链接等信息。方法自调用到执行结束,对应着一个栈帧在虚拟机栈中入栈到出栈。
 
 

本地方法栈

与虚拟机栈很类似,区别在于它不是为Java方法服务,而是为Native方法服务。
 
 

在虚拟机启动时创建,存放对象实例。在存储空间上逻辑连续,物理不一定连续。
对于hotspot虚拟机来说,Class对象比较特殊,它存放在方法区里。
 
 

方法区

存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
 
 

运行时常量池

方法区的一部分。与Class文件常量池的不同在于,运行时常量池还允许运行期间而不仅仅是编译期间置入新的常量。例如String类的intern()方法。
String类的intern方法:如果字符串常量池中已经包含一个等于此String对象的字符串,则返回代表池中这个字符串的String对象;否则,将此String对象包含的字符串添加到常量池中,并且返回此String对象的引用。
 
 

Class文件常量池

主要存放两大类常量:字面量(Literal)和符号引用(Symbolic References)
 
 

直接内存

不是虚拟机运行时数据区的一部分,也不是Java虚拟机规范中定义的内存区域。它是一种堆外内存,通过存储在Java堆中的DirectByteBuffer对象作为这块内存的引用进行操作。
 
 

JVM创建对象的过程

 
     虚拟机遇到new指令

→ 检查常量池中能否定位到一个类的符号引用

→ 检查该类是否已被加载、解析、初始化(若没有则加载)

→ 为对象分配内存(两种方法:指针碰撞or空闲列表)

→ 初始化该内存为零值

→ 设置对象头(哈希码,GC分代年龄,从属于什么类等)

→ 执行方法,将对象按照程序员的意愿进行初始化。
 
 

对象的内存布局

在这里插入图片描述
          对象头Header(包含各种元数据:哈希码、GC分代年龄等等,另外还有类型指针)
 
          实例数据Instance Data(程序代码中所定义的各种类型的字段内容)
 
          对齐填充Padding(使对象大小保持8字节的整数倍)
 
 

对象的访问定位方式

 
使用句柄 or 直接指针
 
使用句柄:
在这里插入图片描述
 
直接指针:
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值