jvm运行时内存是怎么分布的?

原文来自公众号:三不猴子内回复666获取面试资料,回复电子书获取200本PDF电子书

Java内存模型

基础知识。

存储器的结构(摘自深入理解计算机基础第三版P421)

image.png

寄存器中的内存最小速度最快,硬盘容量最大,速度最小,cup的第三级缓存是共享内存。


image.png

对于一个在同一行的数据XY,会被同时加载进CPU,这个现象叫cache line缓存行对齐,缓存行对齐具体内容可以看看这篇文章如果左边的CPU核心加载了X并进行修改,但是此时并没有将数据写回进主内存,或者是第三级缓存,此时右边的CPU核心将X读进,并修改,此时就会产生数据不一致的情况。对于左边修改了数据右边如何才能知道,这是硬件层级需要解决的。 多线程一致性的硬件支持有一下集中方式。

  1. 锁总线的方式。总线锁会锁住bus总线,使得其他CPU不能访问内存中的其他地址,因而效率极低。CPU的共享内存都是通过


    image.png
  2. MESI(英特尔CPU) 等等之类的缓存一致性协议,相对于总线锁的方式MESI的性能好很多。

    1. M: 被修改(Modified) 当一个值被加载到一个CPU内存中,同时这个CPU修改了这个值,则用Modified来表示,以为着在未来某个时刻会将这个值写入进主存。
    2. E: 独享的(Exclusive) 只有当前的CPU才能加载这个数据,就属于Exclusive独享的值。
    3. S: 共享的(Shared) 当多个CPU读取了同一个值,则用Shared来表示。
    4. I: 无效的(Invalid) 当前CPU读取的值已经被修改过了,则这个值是无效的用Invalid表示,以为这未来某个时刻会从主存中读取这个值。
  3. 在特定情况下CPU会进行指令重排,以保证高效的执行。CPU如何保证特定的情况下不不乱序执行。通过内存屏障来保证指令的有序性。

    下面是三种CPU指令内存屏障指令。

    1. sfence:在sfence指令前的写操作必须在sfence后写操作完成之前完成操作。即在两次写操作之间加个屏障使其不能被重排。

    2. lfence:在lfence指令前的读操作必须在lfence后的读操作完成之前完成操作。即在两次读操作之间加个屏障使其不能被重排。

    3. mfence:在mfence指令前的读写操作必须在mfence的读写操作完成之前完成操作。即在一次读一次写和另一次读和一次写之间加一个屏障使其不能被重排。

      CPU保证有序执行除了可以使用mfence,还可以使用

    jvm内存屏障,对上面的CPU内存屏障进行组合,有如下四种屏障

    1. loadload屏障,对于这样的语句Load1; LoadLoad; Load2, 在Load2及后续读取操作要读取的数据被访问前,保证Load1要读取的数据被读取完毕。
    2. storestore屏障,对于这样的语句Store1; StoreStore; Store2,在Store2及后续写入操作执行前,保证Store1的写入操作对其它处理器可见。
    3. loadstore屏障,对于这样的语句Load1; LoadStore; Store2,在Store2及后续写入操作被刷出前,保证Load1要读取的数据被读取完毕。
    4. storeload屏障,对于这样的语句Store1; StoreLoad; Load2,在Load2及后续所有读取操作执行前,保证Store1的写入对所有处理器可见。

Runtime Data Area and Instruction Set

指令集分类

  1. 基于寄存器的指令集
  2. 基于栈的指令集
    Hotspot中的Local Variable Table = JVM中的寄存器

Runtime Data Area

img

PC 程序计数器 Program Counter

Each Java Virtual Machine thread has its own pc (program counter) register.

每个Java虚拟机线程都有自己的程序计数器的存储空间。

At any point, each Java Virtual Machine thread is executing the code of a single method, namely the current method for that thread.

在任何时候,每个Java虚拟机线程都在执行单个方法的代码,即该线程的当前方法。

If that method is not native , the pc register contains the address of the Java Virtual Machine instruction currently being executed.

如果该方法不是本机方法,则pc寄存器包含当前正在执行的Java虚拟机指令的地址。

存放指令位置

虚拟机的运行,类似于这样的循环:

while( not end ) {

取PC中的位置,找到对应位置的指令;

执行该指令;

PC ++;
}

JVM Stack

Each Java Virtual Machine thread has a private Java Virtual Machine stack, created at the same time as the thread.

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

A Java Virtual Machine stack stores frames

每个Java虚拟机存储的都是栈帧

  1. Frame - 每个方法对应一个栈帧
    1. Local Variable Table 局部变量
    2. Operand Stack 操作数堆
      当一个方法刚刚开始执行时,其操作数栈是空的,随着方法执行和字节码指令的执行,会从局部变量表或对象实例的字段中复制常量或变量写入到操作数栈,再随着计算的进行将栈中元素出栈到局部变量表或者返回给方法调用者,也就是出栈/入栈操作。一个完整的方法执行期间往往包含多个这样出栈/入栈的过程。
    3. Dynamic Linking 动态链接
      所谓动态链接就是指向运行时常量池的那个链接,然后看看指向的那个链接有没有解析,如果已经解析直接拿过来使用,没有解析尝试进行解析。表明这个方式叫什么,什么类型等等信息。比如在a()方法中调用了一个b()方法,在a的应用肯定有个b()但是b的具体内容在哪里是dynamic linking去获取。
    4. return address
      a() -> b(),方法a调用了方法b, b方法的返回值放在什么地方

Heap

The Java Virtual Machine has a heap that is shared among all Java Virtual Machine threads.

java 虚拟机有个所有线程共享的堆内存。

The heap is the run-time data area from which memory for all class instances and arrays is allocated.

堆是运行时数据区,从中分配所有类实例和数组的内存。

Method Area

The Java Virtual Machine has a method area that is shared among all Java Virtual Machine threads.

Java虚拟机具有一个在所有Java虚拟机线程之间共享的方法区域。

It stores per-class structures

存储每个类的结构

  1. Perm Space (<1.8)
    字符串常量位于PermSpace
    FGC不会清理
    大小启动的时候指定,不能变
  2. Meta Space (>=1.8)
    字符串常量位于堆(常量池是放在方法区中,所谓常量池比如运行class文件运行产生的一些常量)
    会触发FGC清理
    不设定的话,最大就是物理内存

Runtime Constant Pool

A run-time constant pool is a per-class or per-interface run-time representation of the constant_ pool table ina class file

Native Method Stack

An implementation of the Java Virtual Machine may use conventional stacks called native method stacks

Direct Memory

JVM可以直接访问的内核空间的内存 (OS 管理的内存)

NIO , 提高效率,实现zero copy

上面的内容总结起来就是下面这张图
image.png

每个线程都有自己的栈内存,里面存放的是栈帧,如果有调用native方法就还存在native method stack,还有自己program counter程序计数器,用来记录每条指令的执行,当CPU切换线程的时候方便知道之前线程执行到哪条指令,所有线程共享堆内存和方法区,方法区有两种实现,在jdk8之前方法区叫PermGen永久代,jdk8及其以后的版本都叫Meta Space 元数据区。

栈帧:A frame is used to store data and partial results, as well as to perform dynamic linking, return values for methods, and dispatch exceptions.

栈帧是用来存储数据部分结果,和执行动态链接,返回方法的值和处理异常调度。

image.png

我们看一下一个简单的方法的执行过程的栈帧是怎么样的。

pubilc class Test1{
  pubilc static void main(String [] args){
   Test h = new Test();
    h.m1();
  }
}

pubilc class Test{
  public void m1(){
    int i = 200;
  }
}

编译后的Test1字节码为:

0 new #2 <com/yhx/Test>
3 dup
4 invokespcial #3<com/yhx/Test<init>>
7 istore_1
8 iload_1
9 invokespcial #3<com/yhx/Test<m1>>
12 return

对应Test字节码为:

0 ipush 200
3 istore_1
4 return
image.png

我我们看一下执行过程,在含有主方法的字节码中,首先执行一个new指令。new一个对象的话,包括三个操作:

  1. 首先开辟一个内存空间放在栈帧中,此时就包含了一个Dynamic Linking 动态链接的过程要把 Test h = new Test()中的Test类对应成这个类内存地址;
  2. 然后给这个对象的成员变量付出初始值(不是默认值);
  3. 最后初始化给成员变量一个默认值(init)。

我们看上面指令,在这条 invokespcial #3<com/yhx/Test<init>>也就是初始化之前执行了一个dup指令,也就是上面初始化对象的是哪个流程执行完第二个流程,此时这个对象的成员变量的值如果是引用型的则还是为null,这个dup指令是将main方法栈帧中Operand Stacks的(如上图)h复制一份,然后出栈,init操作拿着出栈后的值进行初始化操作,这个时候栈内的对象引用就变为初始化之后的了。 接下来就是“istore_1”变量1就是h,将初始化好的内存引用赋值给h,然后“iload_1”把变量1加载进本地变量表。

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