java架构之道-JVM内存模型

整体介绍

每当我们去面试时,面试官经常会问jvm相关的问题,谈到JVM,首先不得不说jvm内存模型,今天就来深度剖析一下它,jvm内存模型的结构图如下:


对于jvm内存模型为何要如此设计,下面给你解释一下java程序的运行过程你就明白了:

所谓JVM内存模型实际上的意思是java运行时数据区域,它整个过程就是当程序要执行某一段代码时,类加载器加载我们的class字节码文件,把读取的信息翻译成类信息存放到我们的方法区,同时在堆中生成该类的Class对象,当我们程序运行调用方法时,局部变量、对象引用、数组引用会在虚拟机栈中生成,如果在方法调用中需要new对象,则会在堆中根据Class信息生成对象,最后由我们的字节码执行引擎解释执行方法区的代码块,就完成了我们的代码执行。当然这个过程中,涉及到线程的切换,这时程序计数器就派上用场了,它会记录当前线程执行到哪一行代码,下次该线程再次获取cpu执行权时,继续从该行代码继续执行,最后本地方法栈和虚拟机栈的功能几乎一模一样,只不过它是执行的native本地方法,底层是调用的C或C++代码。

这段话其实就是JVM内存模型的整个执行流程,有点干,没事,我后面会做详细分析,读者只需要大概读一下有个整体印象就行,等我分析完了你再回头来看就会豁然开朗!

注意我会从各个区域使用到的先后顺序来分析,以便读者能够把它们串联起来

各个区域详解

方法区

方法区是存放从class文件加载出来的类信息的,包括常量、静态变量、类信息和运行时常量池。这里有个注意点必须给大家提醒一下,那就是该区域并不会存放Class对象,Class对象是存放在堆中的,方法区存放的类信息是一些代码片段(类似于C语言中的结构体),供我们程序调用时字节码执行引擎解释执行的。

对于方法区在JDK8以前的实现是永久代,之后是元空间,这个网上一搜一大把,我就不多废话了。

虚拟机栈

虚拟机栈是我们进行方法调用的地方,每当一个线程执行代码时,jvm就会为该线程开辟一个私有的栈空间,以下面的代码为例:

 public class Math {
     public static void main(String[] args) {
         int a = 8;
         add(a);
         System.out.println(a);
     }
 
     public static int add(int a){
         a = a++;
         return a;
     }
 }

你知道输出结果是多少吗?我相信不是回答8就是回答9,那么事实是什么呢?且听我慢慢分析

代码执行时栈的结构如下:


在java程序执行时,每调用一次方法,都会创建一个栈帧,栈帧的结构包括局部变量表,操作数栈,动态链接,方法出口,main方法执行时会创建一个栈帧,然后main方法调用add方法创建另外一个栈帧,那么add方法在执行时底层结构是什么样的呢?这时我们需要用javap -c命令反编译我们的Math.class文件,结果如下:


我们来对照着代码逐一分析这几句字节码指令:


iload_0:加载局部变量表中a的值(为8)到操作数栈,注意这时还没有进行++操作,所以此时操作数栈中a的值为8

iinc:对局部变量表中a进行++操作,所以局部变量表中的a值变为9

istore_0:将操作数中的a值赋给局部变量表中的a值,所以此时局部变量表中的a值又变为8

所以最后的答案是8

至于动态链接和方法返回出口有不懂的可以百度一下,网上很多资料,就不再累述了。

java堆

这个区域是java程序员可以控制最多的地方,我们系统新建的对象大部分都在这里分配内存空间,堆的结构如下:


堆由老年代和新生代组成,新建的对象一般都是在存放在Eden区,当Eden区不够用时,就会就行Minior GC,回收垃圾对象释放内存空间,当垃圾回收后任然存活的对象就会放到S0和S1其中一块区域,当再次发生Minior GC时,会把Eden区和有对象的S区中的存活对象移动到另外一块空的S区,这时先前有对象的S区又变成空的S区,所以S0和S1是相互转化的,当S区对象达到一定的阈值时,新生代的对象就会向老年代转移,当老年代的对象达到一定阈值时,就会触发Full GC

本地方法栈

和虚拟机栈的功能几乎一模一样,由于底层是C或C++实现的,我在这里就不过多介绍了(其实是不会)。

程序计数器

用于记录线程执行到哪一行代码,还记得我们上面反编译后得到的字节码指令吗?读者可以认为是字节码中每行指令前面的行号,也就是地址:


各个区域配置参数


各个区域参数配置图中已标好,记不住时读者可以来这里翻阅查找,我想说的一点是你们知道为啥是-X来设置参数吗?而有些时候却要用-D来设置参数,没错,-X表示参数的调用解析方是C或C++代码,-D表示参数的调用解析方是java代码。

文章首发于我的微信公众号-java时光,欢迎关注!


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

推荐阅读更多精彩内容