JVM-1:内存结构

一、 瞎掰

最近在系统地梳理Java虚拟机的知识,想想还是把自己的一些想法记录下来,不然这些所谓的理解迟早都会被懒惰的大脑神经元全部抛弃。尽管记录了也会抛弃,但至少为自己保存了一个搜寻的线索。

二、JVM内存结构概述

首先需要指出的是文章是从HotSpot JVM出发的,Java虚拟机家族有众多虚拟机版本,感兴趣的可以自行查阅相关资料。讲的是JVM内存结构,更确切地说是JVM的运行时数据区结构。JVM的运行时数据区包含了多个内存区域 ,先来看图。


JVM run time areas

上图图源

JVM的多个内存区域既包括了线程私有的区域,也包括了线程共享的区域。如上图所示,线程私有的内存区域有:

  • PC Register(程序计数器)
  • JVM Stack(Java虚拟机栈)
  • Native Method Stack(本地方法栈)

线程共享的内存区域有:

  • Heap(堆)
  • Method Area(方法去)
    • Runtime Constant Pool(运行时常量区)

三、线程私有内存

1. 程序计数器:PC Register

这部分内存的目的是为了记录当前线程执行的字节码行号。结合操作系统的寄存器(Register)就不难理解这部分内存的功能,不要被翻译程序计数器带跑偏,当然为了语言统一我还是会继续使用程序计数器。程序计数器说白了就是 程序运行追踪器,记录线程运行到了字节文件(Class文件)的什么位置。

值得注意的是,这部分内存并不会记录Native方法,当Native方法执行时,计数器值为空。

2. Java虚拟机栈:JVM Stack

这部分内存区域和堆(Heap)应该是我们最为熟悉也最为关注的内存区域了。该内存区域为线程私有,所以它和线程有着一样的生命周期。每个方法(method)在运行时,都会在虚拟机栈中拥有一个自己的栈帧(Stack Frame),栈帧随着方法的执行入栈,随着方法执行结束出栈。栈帧中存有如下数据:

  • 局部变量表
  • 操作数栈
  • 动态链接
  • 方法出口

其中局部变量表在栈帧中的大小是在编译期间就可以确定的,并且这局部变量表的大小在方法运行期间不会被改变。局部变量表当中存放有编译期可知的各种基本数据类型:boolean, byte, char, short, int, float, long, double, 以及对象引用(Reference类型)。这部分两个比较另类的基本数据类型是longdouble,因为两个数据类型都是64位的,在变量表中会占用两个局部变量空间(slot)。但是在所以的时候只使用第一个是空间的值,例如,一个long型数据占用了第3,第4个slot,那寻址的时候只需要使用第3个slot的地址。

因为局部变量表的大小在编译时间就已经确定,所以局部变量表在运行时不会产生StackOverFlowError异常和OutOfMemoryError异常。但是虚拟机栈会产生以上两个异常,主要是基于以下原因:

    1. 线程请求的栈深度大于虚拟机所允许的深度,抛出StackOverFlowError异常
    1. 虚拟机无法给扩展的栈申请到足够的内存,抛出OutOfMemoryError异常

3. 本地方法栈:Native Method Stack

要理解这部分内存区域首先要理解Native Method。本地方法(Native Method) 指的是Java语言中调用的其他语言,简而言之这部分内存是给非Java语言的代码使用的。在HotSpot虚拟机中,这部分内存其实是和虚拟机栈合二为一的。

四、线程共享内存

1. 方法区:Method Area

方法区用于存放已经被虚拟机加载了的类信息、常量、静态变量、即时编译器编译后的代码等数据。方法区在HotSpot中的具体实现可以参考深入理解Java虚拟机 第二版2.2.5,这里不再赘述。

同时,方法区中还拥有运行时常量池(Runtime Constant Pool)。该部分内存用于存放编译期生成的各种字面量和符号引用,通常这些内容在相应的类被加载后放入运行时常量池。

2. 堆:Heap

Java堆是Java虚拟机管理的最大一块内存区域,也是内存收集器的主要活动场所。该内存区域存在的唯一目的就是存放对象实例,几乎所有对象都被存放在这里。请注意,这里是几乎,具体的介绍请看Hollis的对象并不一定都是在堆上分配内存的

因为Java堆是GC活动的主要场所,涉及到相关的垃圾回收机制这里也没法全面概述。前段时间刚好看了一篇介绍Java垃圾回收机制的教程,点击阅读不收费。其中讲述了堆中内存的具体分配,更新迭代,看完一定能堆垃圾回收有一个初步的了解。此外,Java是如何在堆中为对象分配内存、又如何从堆中获取对象都是相对复杂的操作,无法在这一篇概述中详细说明,在深入理解Java虚拟机 第二版2.3中有详细的介绍,翻一下不浪费时间:)。

五、总结

个人认为深入理解JVM内存对现实编程有巨大帮助,比如帮助理解StackOverFlowError等异常,提高编码水平,通过调整虚拟机的内存获取更高的性能等等。这些都可以作为另外一片文章讲解,因为这篇文章只是概述JVM内存的相关结构,具体的如何对内存错误定位,如何通过分配内存提高虚拟机性能等下一篇文章再总结吧。私以为直接内存并不属于JVM管理的内存,也就不再赘述。

六、参考资料

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

推荐阅读更多精彩内容