Java运行时数据区域及其工作原理,对象定位

无论你是跟同事、同学、上下级、同行、或者面试官讨论技术问题的时候,很容易卷入JVM大型撕逼现场。为了能够让大家从大型撕逼现场中脱颖而出,最近我苦思冥想如何把知识点尽可能呈现的容易理解,方便记忆。于是就开启了这一系列文章的编写。为了让JVM相关知识点能够形成一个体系,arthinking将编写整理一系列的专题,以尽量以图片的方式描述相关知识点,并且最终把所有相关知识点串成了一张图。持续更新中,欢迎大家阅读。有任何错落之处也请您高抬贵手帮忙指正,感谢!

导读

  1. JVM是怎么划分内存区域的?
  2. JVM里面各个区之间是怎么配合工作的?
  3. 对象在内存中是如何布局的?
  4. 什么是操作数栈和局部变量表?可否在class文件中展示下?
  5. 运行时常量和字符串常量有什么区别?
  6. 对象访问定位方式有哪些?各有什么优点

1、运行时数据区域

image

注:方法区,Java 8之前也叫PermGen永久带,Java8去掉了永久带,引入了Metaspace元空间。

OOM:OutOfMemory

SO:stackOverflow

1.1、程序计数器

存储:当前线程所执行的字节码的行号指示器。(执行native方法时为空)

这个区不会出现OOM异常。

1.2、Java虚拟机栈

存储:Java方法执行过程中的栈帧(每个方法创建一个栈帧),存储局部变量表,操作数栈,动态链接,方法出口等信息。

局部变量表存放了编译期可知的各种基本数据类型、对象引用和return Address(指向了一条字节码指令的地址)类型。

虚拟机参数设置:-Xss设置虚拟机栈的大小

更多关于Java虚拟机栈的说明:深入理解Java虚拟机笔记---运行时栈帧结构

1.3、本地方法栈

为本地方法服务,JVM规范没有对这块做太多约定,有的虚拟机直接把本地方法栈和虚拟机栈合二为一。

1.4、Java堆

存储:存储对象实例;

垃圾收集器管理的主要区域;

虚拟机参数设置:

  • -Xmx 最大值
  • -Xms最小值

1.5、方法区

存储:存储已加载的类信息,常量,静态变量,即时编译器编译后的代码;

垃圾收集行为在此区域比较少发生;

运行时常量池是方法区的一部分:用于存放编译器生成的各种字面量(static final)和符号引用。

方法区包含class文件信息,class文件信息包含:魔数,版本号,常量池,类父类和接口数组,字段,方法等信息。方法区和常量池

一个class文件对应一个常量池,为静态常量池。JDK运行时,会根据静态常量池生成对应的运行时常量池。

JDK7之前运行时常量池逻辑包含字符串常量池,此时hotspot虚拟机对方法区的实现为永久带

JDK7字符串常量池从方法区移到了堆中,这里只是把字符串常量池单独拿到了堆中,运行时常量池剩下的东西还在方法区,也就是hotspot的永久带;

JDK8中 hotspot移除了永久带,用元空间取代,此时字符串常量池还在堆中,运行时常量池还在方法区,只不过方法区的实现从永久带变成了元空间。JDK1.8关于运行时常量池, 字符串常量池的要点

JDK8的元空间不在JVM运行时数据区,而在本地内存,此时本地内存包括:元数据区(元空间)和直接内存。

1.6、直接内存

不属于JVM运行时数据区;jdk1.4+ NIO可以使用native函数库分配堆外内存。

虚拟机参数设置:-XX:MaxDirectMemorySize

当各区内存大于物理内存限制的时候,会抛出OOM异常。

2、JVM运行时数据区是如何工作的

上面对JVM各个区做了简单的描述,各个区之间是如何在一起工作的呢,下面我们就用一张图来阐述:

image
  • 线程:每个线程都有对应的程序计数器,虚拟机栈,本地方法栈;
  • 虚拟机栈:假设有如下调用关系:ClassA.invokeA() -> ClassB.invokeB() -> ClassB.doInvokeB() -> ClassC.execute(),则会生成以上的虚拟机栈,每个方法调用,都有一个栈帧入栈,调用完成,栈帧从虚拟机栈上出栈;虚拟机栈是一个LIFO的栈;
  • 栈帧:栈帧包含以下内容:
    • 本地变量表:本地变量表长度编译期确定,一个本地变量(Slot)可以存32位以内的数据,可以保存类型为 int, short, reference, byte, char, floath和returnAddress的数据,两个本地变量可以保存类型为long和double的数据;
    • 操作数栈:每个栈帧内部都包含一个称为操作数栈的后进先出栈,提供给方法计算过程使用;
    • 动态链接:每个栈帧都包含一个指向运行时常量池中该栈帧所属方法的引用来支持方法调用过程中的动态链接;Class文件的常量池中包含了大量的符号引用,字节码中的方法调用指令以常量池中指向的符号引用作为参数,这些符号引用通过两种方式最终转换为直接引用:
      • 静态解析:一部分在类加载阶段或者第一次使用的时候转换为直接引用;
      • 动态链接:在运行期间转换为直接引用;
    • 返回地址:在方法退出之后,需要返回到方法被调用的位置继续执行;退出时可能需要执行的操作:
      • 恢复上层方法局部变量表和操作数栈;
      • 如有有返回值,把该值压入调用者栈帧的操作数栈中;
      • 调整PC计数器的值以指向方法调用指令的下一条指令地址。
  • 线程可以访问Java堆方法区

思考

  1. 局部对象和局部int类型分别存储在哪里?

  2. 有如下代码,尝试使用javap工具生成虚拟机汇编代码,查看汇编代码中的本地变量表,以及使用操作数栈和局部变量表的相关指令:

package com.itzhai.jvm;
public class Test {
    public static addOperation() {
       int a = 1;
       int b = 2;
       int c = a + b;
    }
}
  1. 线程是如何访问堆中创建的对象的呢?对象在虚拟机中如何存储?详细参考下一小节

3、HotSpot虚拟机中的对象

3.1、对象的内存布局

对象在内存中存储的布局如下图所示:

image

3.2、对象的访问定位

对象的访问定位有两种方式:直接使用指针访问,通过句柄访问;

3.2.1、直接使用指针访问

image

如上图,我们的Java程序通过栈上的reference数据来操作堆上的具体对象。reference指向了堆中的具体对象。

3.2.2、通过句柄访问

image

如上图,句柄中包含了对象实例数据与类型数据各自的具体地址信息。

对比

  • 使用指针访问方式的好处是速度快;
  • 使用句柄访问的最大好处是reference中存储的是稳定的句柄地址,垃圾回收移动对象的时候,只会改变句柄中实例数据指针,而reference本身不需要修改。

References

深入理解Java虚拟机笔记---运行时栈帧结构

JVM 栈帧

Java 内存区域详解


本文为arthinking基于相关技术资料和官方文档撰写而成,确保内容的准确性,如果你发现了有何错漏之处,烦请高抬贵手帮忙指正,万分感激。

大家可以关注我的博客:itzhai.com 获取更多文章,我将持续更新后端相关技术,涉及JVM、Java基础、架构设计、网络编程、数据结构、数据库、算法、并发编程、分布式系统等相关内容。

如果您觉得读完本文有所收获的话,可以关注我的账号,或者点赞啥的。关注我的公众号,及时获取最新的文章。


本文作者: arthinking

博客链接: https://www.itzhai.com/jvm/how-java-runtime-data-area-works.html

Java运行时数据区域是如何工作的 | JVM内存布局 对象访问定位

版权声明:版权归作者所有,未经许可不得转载,侵权必究!联系作者请加公众号。


image
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,080评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,422评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,630评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,554评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,662评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,856评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,014评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,752评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,212评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,541评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,687评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,347评论 4 331
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,973评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,777评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,006评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,406评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,576评论 2 349