JAVA8 内存模型

参考:https://blog.csdn.net/reachwang/article/details/99755178

通常谈到JVM的内存模型,一般人会想到堆和栈等,那么堆和栈如何理解呢?
是运行时的单位;
是存储的单位。
通俗来说解决的是程序如何运行,数据如何处理的问题;而堆解决的是数据如何存储,存储在哪的问题。

JMM

如上图所示,java虚拟机内存模型主要分为以上五个部分,这里以java8为学习对象。

一、本地方法栈 (Native Method Stacks)

本地方法栈(Native Method Stacks)与虚拟机栈所发挥的作用是非常相似的。其区别在于虚拟机栈为虚拟机执行Java方法所服务,而本地方法栈则是为虚拟机使用到的native方法所服务。

本地方法栈也是一个私有(线程私有)的内存区域,也是后进先出。

虚拟机可以自由实现它,有的虚拟机(如HotSpot虚拟机)直接就把本地方法栈和虚拟机栈合二为一。

本地方法栈区域也会抛出StackOverflowError和OutOfMemoryError异常:

二、虚拟机栈 (Java Virtual Machine Stacks)

每个Java线程都有一个私有Java虚拟机栈,与该线程同时创建。

在虚拟机栈内,每个方法会生成一个栈帧。每个栈帧代表一次次的方法调用,一个方法的执行到执行完成的过程,代表栈帧从入栈到出栈的过程。

虚拟机栈会抛出StackOverflowError和OutOfMemoryError。

2.1 栈帧结构

下图表示了栈帧的组成结构:

栈帧

2.1.1 局部变量表

局部变量表是一组变量值存储空间,用于存放方法参数和方法内部定义的局部变量
具体数据类型的内容参考:https://www.jianshu.com/p/f46e02173552

2.1.2 操作数栈

操作数栈是一个后入先出的栈。

一个方法刚开始执行时操作数栈是空的,方法执行过程中会有各种字节码指令往操作数栈中写入和提取内容,也就是出栈 / 入栈操作。

例如执行iadd指令时,就会将最接近栈顶的两个int元素取出并相加,然后将相加的结果再入栈。

操作数栈中元素的数据类型必须与字节码指令的序列严格匹配,在编译程序代码的时候,编译器要严格保证这一点。比如刚才的iadd指令,它取出的元素必须是int的,不能出现诸如long和float类型的变量。

虽然概念模型中不同栈帧之间是完全相互独立的,但大多虚拟机实现中会有一些优化处理:令两个栈帧出现一部分重叠,让下面的栈帧的部分操作数栈与上面栈帧的部分局部变量表重叠在一起重叠在一起,这样在进行方法调用时就可以公用一部分数据,无须进行额外的参数复制传递,如图所示:

重叠

2.1.3 动态链接

每个栈帧都包含一个指向运行时常量池中该栈帧所属方法的引用,持有这个引用是为了支持方法调用过程中的动态连接。

静态解析:我们知道Class文件的常量池中存有大量的符号引用,字节码中的方法调用指令就以常量池中指向方法的符号引用作为参数,这些符号引用一部分会在类加载阶段或者第一次使用的时候就转化为直接引用,这种转化称为静态解析。

动态链接:除去静态解析的另外一部分将在每一次运行期间转化为直接引用,这部分称为动态链接。

所以要执行某个方法时,某个指令(例如invokevirtual)将常量池中的引用作为参数,而根据这个引用就可以找到真正的栈帧。

关于方法的解析与调用,参考:https://blog.csdn.net/reachwang/article/details/103058653

2.1.4 方法出口

方法出口也可以通俗的理解为方法返回方式:在jvm中,方法返回方式有两种:正常异常

正常出口:当程序执行遇到方法返回的字节码指令,就完成此次方法执行,并根据调用方指定的返回值去返回(可以无返回值)。
异常出口:方法在执行中遇到了异常,并且在方法体内没有得到处理,会导致方法退出,这时候不会有任何返回值给调用方。

一个方法退出时需要返回到其被调用的位置,上层调用方法才能继续执行。

程序正常退出时,相当于把当前栈帧出栈,调用pc计数器的值作为返回地址,即调用该方法的指令的下一条指令的地址。

程序异常退出时:当程序发生异常时,返回地址需要通过异常表来确定,在栈帧中没有保存异常表。

2.2 虚拟机栈与本地方法栈的关系

为了更好地理解虚拟机栈和本地方法栈的结构模型以及关系,我们以网上的例子简单描述下,如下图:

虚拟机栈与本地方法栈的相互调用

三、寄存器 (The pc Register)

Java虚拟机可以支持多个线程同时执行,每个Java线程都有其自己的 pc(程序计数器)寄存器。在任何时候,每个Java虚拟机线程都在执行单个方法的代码,即该线程的当前方法。(如果不是native,则该pc寄存器包含当前正在执行的Java虚拟机指令的地址。如果线程当前正在执行的方法是native,则Java虚拟机的pc寄存器值未定义。

pc寄存器中的值就是当前指令所在的内存地址,即returnAddress类型的数据,当线程执行native方法时,pc中的值为undefined。

四、方法区 (Method Area)

Java虚拟机具有一个在所有Java虚拟机线程之间共享的方法区域。该方法区域类似于常规语言的编译代码的存储区域,或者类似于操作系统过程中的“文本”段。它存储每个类的结构,例如运行时常量池,字段和方法数据,以及方法和构造函数的代码,包括用于类和实例初始化以及接口初始化的特殊方法。

方法区是在虚拟机启动时创建的。尽管方法区在逻辑上是堆的一部分,但是可以选择不进行垃圾回收或压缩。该规范没有规定方法区域的位置或用于管理已编译代码的策略。方法区域可以是固定大小的,或者可以根据计算的需要进行扩展,如果不需要更大的方法区域,则可以缩小。方法区域的内存不必是连续的。

可能抛出OutOfMemoryError异常。

五、堆 (Heap)

Java虚拟机具有一个在所有Java虚拟机线程之间共享的堆。堆是运行时数据区,从中分配所有类实例和数组的内存。

堆是在虚拟机启动时创建的。对象的堆存储由GC(垃圾收集器)回收;对象永远不会显式释放。Java虚拟机可以根据实现者的系统要求选择GC。堆的大小可以是固定的,也可以根据计算要求进行扩展,如果不需要更大的堆,则可以将其收缩。堆的内存不必是连续的。

可能抛出OutOfMemoryError异常。

在jdk1.8之前的版本堆内存空间是不同的,主要却别在于:1.8中删除了永久代,新增了元空间。

元空间的本质和永久代类似,都是对JVM规范中方法区的实现。不过元空间与永久代之间最大的区别在于:元空间并不在虚拟机中,而是使用本地内存。因此,默认情况下,元空间的大小仅受本地内存限制,但可以通过参数来指定元空间的大小。

堆内存

jvm中的常量池

参考文章:https://blog.csdn.net/weixin_40999907/article/details/87907083
方法区:运行时常量池
Class文件:常量池
堆:String常量池

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

推荐阅读更多精彩内容