JVM学习(1):JVM的内存结构

关于Java虚拟机这块内容的学习我是看CSDN的一位博客专家大佬@黄小斜的文章学习的,它写的内容更为全面详细,有兴趣可以去看它的文章:深入理解JVM虚拟机1:JVM内存的结构与永久代的消失
这里仅对此文进行笔记整理。

在了解Java虚拟机之前,首先要了解JDK、JRE、JVM分别是指什么:

JDK(Java Development Kit) 是 Java 语言的软件开发工具包(SDK)。一系列工具帮助开发者创建Java应用程序。JDK包含工具编译、运行、打包、分发和监视Java应用程序。

JRE(Java Runtime Environment)Java 运行时环境,JRE 物理存在,主要由Java API 和 JVM组成,提供了用于执行 java 应用程序最低要求的环境。

JVM(Java Virtual Machine) 是一种软件实现,执行像物理机程序的机器(即电脑)。

Java虚拟机即JVM 可执行以下操作:加载代码、验证代码、执行代码、提供运行环境。它提供定义了:存储区、类文件格式、寄存器组、垃圾回收堆、致命错误报告等。

JVM内存结构

JVM内存结构主要有三大块:堆内存、方法区和栈。Java堆是垃圾收集器管理的主要区域,因此很多时候也被称做“GC堆”。方法区与Java堆一样,是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。我们本次主要是需要了解Java堆。
堆内存是JVM中最大的一块由年轻代和老年代组成,而年轻代内存又被分成三部分,伊甸区(Eden空间)、幸存者区域(Survivor Sapce)(From Survivor空间、To Survivor空间),默认情况下年轻代按照8:1:1的比例来分配。

新生代(Eden,伊甸园)
Eden 是内存中的一个区域, 用来分配新创建的对象。通常会有多个线程同时创建多个对象, 所以 Eden 区被划分为多个 线程本地分配缓冲区(Thread Local Allocation Buffer, 简称TLAB)。通过这种缓冲区划分,大部分对象直接由JVM 在对应线程的TLAB中分配, 避免与其他线程的同步操作。
如果 TLAB 中没有足够的内存空间, 就会在共享Eden区(shared Eden space)之中分配。如果共享Eden区也没有足够的空间, 就会触发一次 年轻代GC 来释放内存空间。如果GC之后 Eden 区依然没有足够的空闲内存区域, 则对象就会被分配到老年代空间(Old Generation)。
当 Eden 区进行垃圾收集时, GC将所有从 root 可达的对象过一遍, 并标记为存活对象。标记阶段完成后, Eden中所有存活的对象都会被复制到存活区(Survivor spaces)里面。整个Eden区就可以被认为是空的, 然后就能用来分配新对象。这种方法称为 “标记-复制”(Mark and Copy): 存活的对象被标记, 然后复制到一个存活区(注意,是复制,而不是移动)。

存活区(Survivor Spaces)
Eden 区的旁边是两个存活区, 称为 from 空间和 to 空间。需要着重强调的的是, 任意时刻总有一个存活区是空的(empty)。
空的那个存活区用于在下一次年轻代GC时存放收集的对象。年轻代中所有的存活对象(包括Edenq区和非空的那个 “from” 存活区)都会被复制到 ”to“ 存活区。GC过程完成后, ”to“ 区有对象,而 ‘from’ 区里没有对象。两者的角色进行正好切换 。
存活的对象会在两个存活区之间复制多次, 直到某些对象的存活 时间达到一定的阀值。分代理论假设, 存活超过一定时间的对象很可能会继续存活更长时间。
这类“ 年老” 的对象因此被提升(promoted )到老年代。提升的时候, 存活区的对象不再是复制到另一个存活区,而是迁移到老年代, 并在老年代一直驻留, 直到变为不可达对象。
为了确定一个对象是否“足够老”, 可以被提升(Promotion)到老年代,GC模块跟踪记录每个存活区对象存活的次数。每次分代GC完成后,存活对象的年龄就会增长。当年龄超过提升阈值(tenuring threshold), 就会被提升到老年代区域。
如果存活区空间不够存放年轻代中的存活对象,提升(Promotion)也可能更早地进行。

老年代(Old Generation)
老年代的GC实现要复杂得多。老年代内存空间通常会更大,里面的对象是垃圾的概率也更小。
老年代GC发生的频率比年轻代小很多。同时, 因为预期老年代中的对象大部分是存活的, 所以不再使用标记和复制(Mark and Copy)算法。而是采用移动对象的方式来实现最小化内存碎片。老年代空间的清理算法通常是建立在不同的基础上的。原则上,会执行以下这些步骤:

  1. 通过标志位(marked bit),标记所有通过 GC roots 可达的对象。
  2. 删除所有不可达对象。
  3. 整理老年代空间中的内容,方法是将所有的存活对象复制,从老年代空间开始的地方,依次存放。
    通过上面的描述可知, 老年代GC必须明确地进行整理,以避免内存碎片过多。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值