jvm内存区域

3 篇文章 0 订阅
1 篇文章 0 订阅

jvm内存区域

在这里插入图片描述

  • JVM内存区域主要分为线程私有区域[虚拟机栈、本地方法栈、程序计数器],线程共享区域[方法区、堆]
  • 线程私有区域的生命周期和线程一致;线程共享区域的生命周期和jvm一致。

虚拟机栈(线程私有)

  • 描述java方法执行的内存模型,每个方法在执行的同时都会创建一个栈帧,用于存储局部变量表,操作数栈、动态链接和方法出口信息。每个方法从调用直至执行完成的过程对应着一个栈帧在虚拟机中入栈和出栈的过程。
  • 虚拟机栈是线程隔离的,即每个线程都有自己独立的虚拟机栈()。
  • 若单个线程请求的栈深度大于虚拟机允许的深度,则会抛出StackOverflowError(栈溢出错误)(-Xss参数)。
  • 当整个虚拟机栈内存耗尽,并且无法再申请到新的内存时抛出OutOfMemoryError异常。

本地方法栈(线程私有)

  • 本地方法栈则是为虚拟机使用到的 Native 方法服务。
  • 本地方法栈会抛出 StackOverflowErrorOutOfMemoryError 异常。
  • 本地方法栈是一个后入先出(Last In First Out)栈。

程序计数器(线程私有)

  • 程序计数器是一块较小的内存空间,它可以看做是当前线程所执行的字节码的行号指示器。
  • JVM规范中唯一没有规定OutOfMemoryError情况的区域。
  • 如果正在执行的是Native 方法,则这个计数器值为空。
  • 线程私有。为了线程切换后依然能恢复到原位,每条线程都需要有各自独立的程序计数器

  • 是被线程共享的一块内存区域,创建的对象和数组都保存在 Java 堆内存中,也是垃圾收集器进行

    垃圾收集的最重要的内存区域。

  • Java 堆从 GC 的角度还可以细分为: 新生代(Eden 区、From Survivor 区和 To Survivor 区)和老年 代。
    在这里插入图片描述

新生代

  • 是用来存放新生的对象。一般占据堆的 1/3 空间。由于频繁创建对象,所以新生代会频繁触发 Minor GC 进行垃圾回收。新生代又分为 Eden 区、Servivor区。Survivor 区域分别被命名为 from 和 to,以示区分。无论什么时候,总是有一块 Survivor 区域是空闲着的。因此,新生代实际可用的内存空间为 9/10 ( 即90% )的新生代空间。

  • Eden区:Java 新对象的存储区(如果新创建的对象占用内存很大,则直接分配到老 年代)。当 Eden 区内存不够的时候就会触发 Minor GC,对新生代区进行 一次垃圾回收。

  • ServivorFrom:MinorGC后的幸存对象存储区域。

  • Servivorto:MinorGC过程中幸存对象存储区域。

  • MinorGC 的过程(复制->清空->互换):基于复制算法

    1. 首先,把 Eden 和 ServivorFrom 区域中存活的对象复制到 ServivorTo 区域(如果有对象的年 龄以及达到了老年的标准,则赋值到老年代区),同时把这些对象的年龄+1(如果 ServivorTo 不 够位置了就放到老年区)
    2. 然后,清空 Eden 和 ServivorFrom 中的对象;
    3. 最后,ServicorTo 和 ServicorFrom 互换。

老年代

  • 主要存放应用程序中生命周期长的内存对象。

  • 在进行 Major GC(Full GC) 前一般都先进行 了一次 Minor GC,使得有新生代的对象晋身入老年代,导致空间不够用时才触发。当无法找到足 够大的连续空间分配给新创建的较大对象时也会提前触发一次 Major GC 进行垃圾回收腾出空间。

  • Major GC(Full GC):采用标记清除算法:首先扫描一次所有老年代,标记出存活的对象,然后回收没

    有标记的对象。

CMS算法中的promotion failed和concurrent mode failure

  • promotion failed:当年轻代进行Minor GC的时候,survivor区域内存空间不够时将对象放入老年代,此时老年代也放不下造成的。
  • concurrent mode failure:执行CMS GC的过程中同时业务线程将对象放入老年代,而此时老年代空间不足,或者在做Minor GC的时候,新生代Survivor空间放不下,需要放入老年代,而老年代也放不下而产生的

方法区/永久代

  • 用于存储被 JVM 加载的类信息、常量、静态变量、即时编译器编译后的代码等数据.

  • 运行时常量池用于存放编译期生成的各种字面量和符号引用,这部分内容将在类加 载后存放到方法区的运行时常量池中。

  • 在 Java8 中,永久代已经被移除,被一个称为“元数据区”(元空间)的区域所取代。元空间

    的本质和永久代类似,元空间与永久代之间最大的区别在于:元空间并不在虚拟机中,而是使用

    本地内存。因此,默认情况下,元空间的大小仅受本地内存限制。类的元数据放入 native

    memory, 字符串池和类的静态变量放入 java 堆中,这样可以加载多少类的元数据就不再由

    MaxPermSize 控制, 而由系统的实际可用空间来控制。

emory, 字符串池和类的静态变量放入 java 堆中,这样可以加载多少类的元数据就不再由

MaxPermSize 控制, 而由系统的实际可用空间来控制。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值