当前位置: 首页 > news >正文

虚拟机(一):Java 篇

虚拟机(一):Java 篇

虚拟机(二):Android 篇


架构

运行时数据区:
在这里插入图片描述
栈:
在这里插入图片描述
堆:
在这里插入图片描述

  • 堆:通过new创建的对象都在堆中分配。OutOfMemoryError
    • TLAB(Thread Local Allocation Buffer,线程私有分配缓冲区)
  • 方法区:储了类代码和方法代码。OutOfMemoryError
    • 运行时常量池(Runtime Constant Pool)
  • 虚拟机栈:一个Java程序可能创建了多个线程,每个线程都会有自己的栈。StackOverflowError和OutOfMemoryError
    • 局部变量:方法参数和方法中定义的局部变量
    • 操作数栈:后入先出的栈
    • 动态连接:指向运行时常量池该栈桢所属方法的引用
    • 返回地址:当前方法的返回地址
  • 本地方法栈:本地方法(例如:C/C++语言)执行的区域。StackOverflowError和OutOfMemoryError
  • 程序计数寄存器:存储了执行指令的内存地址。无

判断对象引用

引用计数法:

  • 给对象添加一个引用计数器,每当被引用的时候,计数器的值就加一。引用失效的时候减一,当计数器的值为 0 的时候就表示该对象可以被 GC 回收了。
  • 引用计数无法解决循环引用问题:假设对象A,B都已经被实例化,让A=B,B=A,除此之外这两个对象再无任何引用,此时计数器的值就永远不可能为0,但是引用计数器无法通知gc回收他们

根搜索算法(可达性算法) GC Roots Tracing:

  • 通过一个叫 GC Roots 的对象作为起点,从这些结点开始向下搜索,搜索所走过的路径称为引用链,当一个对象没有与任何的引用链相连的时候则该对象就可以被GC 回收了。
  • 虚拟机中垃圾回收的根对象通常是下面这四种类型的对象
    • 栈中的local变量,即方法中的局部变量
    • 活动的线程(包括主线程和应用程序创建的子线程)
    • static变量
    • JNI中的引用

垃圾收集算法

  • 标记-清除算法:分为标记和清除两个阶段。该算法首先从根集合进行扫描,对存活的对象标记,标记完毕后,再扫描整个空间中未被标记的对象并进行回收。整个过程需要暂停整个程序的全部运行线程,让回收线程以单线程进行工作,过程结束再恢复运行线程。

    1. 效率问题。标记和清除过程的效率都不高。
    2. 空间问题。标记清除之后会产生大量不连续的内存碎片,空间碎片太多可能导致,程序分配较大对象时无法找到足够的连续内存,不得不提前触发另一次垃圾收集动作。
  • 标记-整理算法:标记过程仍然与“标记-清除”算法一样,但不是直接对可回收对象进行清理。该算法在回收期间会同时将保留下来的对象移动聚集到连续的内存空间,从而避免内存空间碎片。但对象的移动是需要时间成本的。

  • 复制算法:

    • 该算法会将所拥有的内存空间分成两个部分。程序运行所需的存储对象先存储在其中一个分区中(例如:定义为“分区0”)。算法执行过程中暂停整个程序的全部运行线程后,进行标记,然后将保留下来的对象移动聚集到另一个分区(例如:定义为“分区1”),这样便完成了回收。在下一次回收时,两个分区的角色对调。很显然,这种算法虽然避免了内存碎片,但对内存空间的使用是比较浪费的,因为始终只能有一半的空间用来使用。
    • 商业的虚拟机都采用复制算法来回收新生代。因为新生代中的对象容易死亡,所以并不需要按照1:1的比例划分内存空间,而是将内存分为一块较大的 Eden 空间和两块较小的 Survivor 空间。每次使用 Eden 和其中的一块 Survivor。当回收时,将 Eden 和 Survivor 中还存活的对象一次性拷贝到另外一块 Survivor 空间上,最后清理掉 Eden 和刚才用过的 Survivor 空间。Hotspot 虚拟机默认 Eden 和 Survivor 的大小比例是8:1,也就是每次新生代中可用内存空间为整个新生代容量的90%(80% + 10%),只有10%的内存是会被“浪费”的。特别地,当survivor1区也不足以存放eden区和survivor0区的存活对象时,就将存活对象直接存放到老年代。如果老年代也满了,就会触发一次FullGC,也就是新生代、老年代都进行回收。注意,新生代发生的GC也叫做MinorGC,MinorGC发生频率比较高,不一定等 Eden区满了才触发
    • “复制”算法在极端的情况下,会出现明显的问题,例如:某些很大的对象,它们的生命周期又很长,那么这些对象便会在分区之间来回移动,这显示是很耗时的。
  • 增量回收:该算法将所拥有的内存空间分成若干分区。程序运行所需的存储对象会分布在这些分区中,每次只对其中一个分区进行回收操作,从而避免程序全部运行线程暂停来进行回收,允许部分线程在不影响回收行为而保持运行,并且降低回收时间,增加程序的响应速度。

  • 分代收集算法

    • 新生代:每次垃圾收集时会有大批对象死去,只有少量存活,所以选择复制算法,只需要少量存活对象的复制成本就可以完成收集。
    • 老年代:对象存活率高、没有额外空间对它进行分配担保,必须使用“标记-清理”或“标记-整理”算法进行回收。
    • 永久代:用于涉及程序整个运行生命周期的对象存储,该空间通常不进行垃圾回收的操作。存储不变的类定义、字节码和常量等。
    • 通过分代,存活在局限域,小容量,寿命短的存储对象会被快速回收;存活在全局域,大容量,寿命长的存储对象就较少被回收行为处理干扰。

相关文章:

  • 与Aspose.pdf类似的jar库分享
  • C++三大特性之继承
  • 数字化转型的点线面体:从局部突破到生态构建
  • 2181、合并零之间的节点
  • GD32 ISP下载程序(串口烧录)
  • 31天Python入门——第14天:异常处理
  • leetcode 2829. k-avoiding 数组的最小总和 中等
  • 单例模式(Singleton Pattern)
  • ubuntu下终端打不开的排查思路和解决方法
  • 硬件基础--04_电场_电势_电势能
  • 解决centos部署的java项目上传文件成功后,访问403
  • SQL注入操作
  • EF Core 执行原生SQL语句
  • 大模型应用平台架构
  • Android 12系统源码_系统启动(二)Zygote进程
  • 批量处理word里面表格单元格中多余的回车符
  • JavaScrip-模版字符串的详解
  • 文献学习:单细胞+临床+模型构建 | 一篇Molecular Cancer文献如何完整解读CDK4/6i耐药机制
  • http 和 https
  • 《云原生安全攻防》-- K8s容器安全:使用gVisor构建安全沙箱运行环境
  • 关税风暴下,3G资本拟94亿美元私有化美国鞋履巨头斯凯奇,溢价30%
  • 外交部:中欧关系50年发展最宝贵经验是相互尊重,求同存异
  • “五一”假期国内出游3.14亿人次,同比增长6.4%
  • 韩国总统选举民调:共同民主党前党首李在明支持率超46%
  • 上海成五一国内最热门的入境游目的地,国际消费明显提升
  • 菏泽家长“付费查成绩”风波调查:免费功能被误读