zoukankan      html  css  js  c++  java
  • JVM 内存模型

    GitHub Page:http://blog.cloudli.top/posts/JVM-内存模型/

    抽象模型

    JVM 内存模型

    程序计数器(Program Counter Register)

    • 程序计数器是 JVM 中一块较小的内存区域,保持当前线程执行的字节码指令的内存地址。
    • 如果线程执行的是 Java 方法,计数器记录的是正在执行的字节码指令的地址,如果正在执行的是 native 方法,计数器的值为 undefined。
    • 为了使线程切换后能够恢复到正确的执行位置,每个线程都有一个独立的程序计数器,各线程互不影响。

    程序计数器

    虚拟机栈(VM Stack)

    栈帧

    虚拟机栈是线程隔离的,每个线程都有自己独立的虚拟机栈,这个栈中又会包含多个栈帧。

    • 每调用一个方法时就会往栈中压入一个栈帧
    • 栈帧存储局部变量表、操作栈、动态链接、方法出口等信息。
    • 每一个方法从调用到返回的过程,就对应一个栈帧从入栈到出栈的过程

    虚拟机栈

    虚拟机栈的内存通过 -Xss 参数分配。

    本地方法栈(Native Method Stack)

    • 本地方法栈的功能和特点与虚拟机栈类似,具有线程隔离的特点,能抛出 StackOverFlowError 和 OutOfMemory 异常。
    • 本地方法栈服务的是对象是 JVM 执行的 native 方法。

    HotSpot 虚拟机不区分虚拟机栈和本地方法栈,两者是一块。

    方法区(Method Area)

    方法区

    • 保存被加载过的类的信息,static 变量信息也保存在方法区中。
    • 方法区是线程共享的,当有多个线程都用到一个类的时候,而这个类还没有加载,则应该只有一个线程去加载类,让其他线程等待。

    方法区

    堆(Heap)

    在 JVM 所管理的内存中,堆区是最大的一块。Java 堆可以处于物理上不连续的内存空间中,只要逻辑上是连续的即可。

    堆

    堆分为新生代和老年代。新生代又分为 Eden、Survivor From、Survivor To 三个区,他们的比例为 8 : 1 : 1

    • Eden 区:新对象的出生地(如果新对象占用内存很大,会直接分配到老年代)。当 Eden 区内存不够时会触发 MinorGC。
    • Survivor From 区:上一次 MinorGC 的存活对象。
    • Survivor To 区:保留了一次 MinorGC 中存活的对象。

    新生代 MinorGC 使用复制算法

    1. 首先将 Eden 和 Survivor From 区中存活的对象复制到 Survivor To 区(如果对象的年龄达到了老年的标准,放置到老年区);
    2. 把这些对象的年龄 +1(如果 Survivor To 空间不够则放置到老年区);
    3. 清空 Eden 和 Survivor From 区中的对象,将 Survivor To 和 Survivor From 互换,原来的 Survivor To 成为了下一次 MinorGC 时的 Survivor From 区。

    老年代的对象比较稳定,MajorGC 不会频繁执行。MajorGC 使用标记-整理算法

    1. 扫描老年代对象,标记被回收对象。
    2. 将存活对象都向一端移动,然后清理掉端边界外的内存。

    堆

    可以通过参数 -Xmx -Xms 来指定运行时堆内存大小。

  • 相关阅读:
    Java实现 LeetCode 136 只出现一次的数字
    Java实现 LeetCode 136 只出现一次的数字
    Java实现 LeetCode 136 只出现一次的数字
    Java实现 LeetCode 135 分发糖果
    Java实现 LeetCode 135 分发糖果
    Java实现 LeetCode 135 分发糖果
    Java实现 LeetCode 134 加油站
    Java实现 LeetCode 134 加油站
    Java实现 LeetCode 134 加油站
    Java实现 LeetCode 133 克隆图
  • 原文地址:https://www.cnblogs.com/cloudfloating/p/11650443.html
Copyright © 2011-2022 走看看