浅析java垃圾回收机制

2023-10-26

一、什么是垃圾回收?
1.垃圾回收,顾名思义,便是将已经分配出去的,但却不再使用的内存回收回来,以便能够再次分配。在 Java 虚拟机的语境下,垃圾指的是死亡的对象所占据的堆空间。
垃圾回收只会负责释放那些对象占有的内存,此时对象也就被销毁。
2. 发生地点:一般发生在堆内存中,因为大部分的对象都储存在堆内存中
3.发生时间:程序空闲时间不定时回收
二、无任何对象引用的对象,通过哪些算法找到这些对象呢?
1.引用计数法(不使用)
给对象增加一个引用计数器,
每当有一个地方引用它时,计数器就+1(a = b, b被引用,则b引用的对象计数+1);
当引用失效(一个对象的某个引用超过了生命周期或者被设置为一个新值时)时,计数器就-1;
任何时刻计数器为0的对象就是不能再被使用的。
缺点:无法解决对象的循环引用的问题
2.可达性分析算法
(1)核心思想:通过一系列名为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象到GC Roots没有任何引用链相连时,就证明此对象是不可用的。
(2)

对象Object5-Object7之间虽然彼此还有关联,但是它们到GC Roots是不可达的,因此他们会被判定为可回收对象。
首先,垃圾回收器将某些特殊的对象定义为GC根对象。所谓的GC根对象包括:
(a)java栈和native栈中所引用的对象。
(b)方法区中的常量和静态变量。
(c)活跃线程
接下来,垃圾回收器会对内存中的整个对象图进行遍历,它先从GC根对象开始,然后是根对象引用的其它对象。回收器将访问到的所有对象都标记为存活。
三、垃圾回收算法
1.标记-清除算法
(1)是最基础的收集算法,算法分为“标记”和“清除”两个阶段:首先标记出需要回收的对象,再标记完成后统一回收所有被标记的对象。它的标记过程其实就是可达性分析算法中判定垃圾对象的标记过程。
(2)优点:不需要进行对象的移动,并且仅对不存活的对象进行处理,在存活对象比较多的情况下极为高效。
(3)缺点:
(a)效率问题:标记和清除过程的效率都不高。(这种方法需要使用一个空闲列表来记录所有的空闲区域以及大小。对空闲列表的管理会增加分配对象时的工作量。
(b)空间问题:标记清除后会产生大量不连续的碎片,空间碎片太多可能会导致以后再程序运行中需要分配较大对象时,无法找到足够连续内存而不得不提前除法另一次垃圾回收。

2.复制算法(新生代回收算法)
(1)复制算法是为了解决“标记-清除”算法的效率问题。
(2)核心思想:他将可用的内存按容量划分为大小相等的两块,每次使用其中的一块,当这块内存需要进行垃圾回收时,会将此区域还存货的对象复制到另一块上面,然后再把已经使用过的内存区域一次清理掉。
(3)优点:性能比较高
缺点:内存利用率低

3.标记-整理算法(老年代回收算法)
让所有的存活对象都向一端移动,然后直接清理掉端边界以外的内存。

4.分代收集算法
当前JVM垃圾收集都采用的是“分代收集”算法,是根据对象存货周期的不同将内存划分为几块。
分代收集算法分为新生代和老年代。
新生代中98%的对象都是"朝生夕死"的,所以并不需要按照1 : 1的比例来划分内存空间,而是将内存(新生代内存)分为一块较大的Eden(伊甸园)空间和两块较小的Survivor(幸存者)空间,每次使用Eden和其中一块Survivor(两个Survivor区域一个称为From区,另一个称为To区域)。当回收时,将Eden和Survivor中还存活的对象一次性复制到另一块Survivor空间上,最后清理掉Eden和刚才用过的Survivor空间。当Survivor空间不够用时,需要依赖其他内存(老年代)进行分配担保。
HotSpot (JDK1.3之后使用的java虚拟机) 默认Eden与Survivor的大小比例是8 : 1,也就是说Eden:Survivor From : Survivor To = 8:1:1。所以每次新生代可用内存空间为整个新生代容量的90%,而剩下的10%用来存放回收后存活的对象。
四、垃圾回收算法总结
1.把java堆分为新生代和老年代.
(1)新生代:第一次创建的对象会被分配到此区域。
(2)老年代:经历了一定(HotSpot默认的执行次数是15,经历了15GC就会从新生代移动到老年代)的垃圾回收之后,依然存活下来的对象会移动到老年代。
大对象在创建的时候也会直接进入老年代。(大对象的初始化比较耗时,如果频繁的创建和消耗会带来性能开销,因此最好的实现方式是将他存入GC频率更低的老年代)
2.在新生代中,每次垃圾回收都有大批对象死去,只有少量存活,因此采用复制算法。
老年代对象存活率更高,没有额外的空间对它进行分配担保,因此采用标记-清除算法或者标记-整理算法。
3.面试:请问了解Minor GC和Full GC,这两种GC有什么不一样吗?
(1)Minor GC :称为新生代GC,指发生在新生代的垃圾回收集。因为java对象大多都是具备朝生夕灭的特性,因此Minor GC(采用复制算法)非常频繁,一般回收速度也快。
(2)Full GC:老年代GC或者Major GC,指发生在老年代的垃圾会收集。出现了Full GC经常会伴随至少一次的Minor GC。由于老年代中的对象生命周期比较长,因此Major GC并不频繁,一般都是等待老年代满了后才进行Full GC,Major GC的速度一般会比Minor GC慢10倍以上。
五、垃圾回收器:垃圾回收器好不好,主要是看SWT(Stop The World)时间的长短,时间短说明好

(1)Serial:单线程串行的垃圾回收器(新生代:复制算法)

(2)Serial Old:老年代的垃圾回收器,标记-整理算法。
(3)PerNew:并行垃圾回收器(单线程串行垃圾回收器的多线程版本,复制算法)

(4)parallel:并发垃圾回收器(新生代)
GC线程和用户线程可以同时执行。
(5)并发垃圾回收器(老生代)

重点:
(6)CMS:是一种以获取最短回收停顿时间为目标的收集器(并发标记和并发清理可以和用户线程一块执行)
老年代收集器,并发GC。
基于标记-清楚算法实现的。
特点:更少的STW。适用场景:用户交互系统b/s(不能让用户等待太长时间)
优点:并发收集,低停顿。

(7)G1:JDK 11默认的垃圾回收器:唯一一款全区域的垃圾回收器
用在heap memory很大的情况下,把heap划分为很多很多的region块,然后并行的对其进行垃圾回收。
G1垃圾回收器在清除实例所占用的内存空间后,还会做内存压缩。
化整为零的思想,将大的内存划分为无数小的内存。
既不属于新生代,也不属于老年代。
G1最大的优势就在于可预测的停顿时间模型,我们可以自己通过参数-XX:MaxGCPauseMillis来设置允许的停顿时间(默认200ms),G1会收集每个Region的回收之后的空间大小、回收需要的时间,根据评估得到的价值,在后台维护一个优先级列表,然后基于我们设置的停顿时间优先回收价值收益最大的Region。

六、java的内存空间
1.堆:线程共享区域
new Object() 所有的对象都是存在此区域,此区域也是JVM中最大的一块区域。
java垃圾回收就是针对此区域。
2.JVM栈(java虚拟机栈):java方法执行的内存模型(线程私有)
栈中的信息:
(1)局部变量表:存储8大基础的数据类型和对象的引用(指针)
(2)操作栈:每个方法都会对应一个操作栈
(3)动态连接:指向常量池的方法引用
(4)方法返回地址:PC寄存器的地址
3.本地方法栈:线程私有
本地方法栈与虚拟机栈的作用完全一样,他俩的区别无非是本地方法栈为虚拟机使用的Native(c/c++)方法服务,而虚拟机栈为JVM执行的Java方法服务
4.程序计数器:线程私有
用来记录线程执行的行号
5.元空间(JDK 1.8):线程共享
在逻辑上属于JVM,但是这部分的空间已经变成本地空间,并且字符串常量池移动到堆里面了。
JDK 1.7 叫做方法区(永久代)属于JVM
方法区存储:运行时常量池,字符串常量池,类的元信息等

七、类加载机制
(1)加载:根据类路径全名加载二进制流。-》将静态的存储结构转换为运行时的数据结构-》在内存中生成一个此类的方法入口
(2)校验:文件格式进行校验-》字节码校验
验证是连接阶段的第⼀步,这⼀阶段的⽬的是确保Class⽂件的字节 流中包含的信息符合《Java虚拟机规范》的全部约束要求,保证这些信息被当作代码运⾏后不会危害虚拟机⾃身的安全。
(3)准备:准备阶段是正式为类中定义的变量(即静态变量,被static修饰的变量)分配内存并设置类变量初始值的阶段。
(4)解析:初始化final修饰的常量
(5)初始化:此步骤开始将执行权从JVM转移到自己写的程序,开始执行构造函数。
(6)使用
(7)卸载
八、JVM双亲委派模型
1.当加载一个类的时候,这个类不会直接加载,而是将这个加载任务直接交给父类。当找不到父类的时候,自己才尝试去加载。
2.优点:
(1)唯一性(父类执行加载一次)
(2)安全性(会往上找,而上层的类是系统提供的类,避免加载自定义的类)

JMM(java内存模型):让JVM高速运行的一种技术
1.JVM:将程序员可以看懂的代码转化为机器码
2.目的:规范和解决不同操作系统之间的缓存和内存的交换关系。让Java程序在各种平台下都能达到一致的内存访问效果
3.主内存和工作内存(CPU的缓存,离CPU更近,操作更快)

变量声明在主内存中,每个线程在操作变量的时候为了提高性能,从主内存将变量读取到工作内存中,再对工作内存中的变量进行操作,再将操作结果save到主内存中。
4.JMM三大特性:
(1)原子性:要么一块成功,要么一块失败
(2)内存可见性:一个线程操作共享变量之后其他线程是可见的
(3)有序性
5.volatile:
保证:内存可见性,禁止指令重排序
6.面试:说一下JMM
(1)JMM作用:解决不同操作系统在操作内存时的性能差异的,以为它要用到工作内存(CPU的缓存),想让自己的执行性能更加的高
(2)规定:把内存规定为两部分内存:工作内存,主内存(交互方法)
(3)三大特征
(4)可见性和有序性怎么保证:volatile

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

浅析java垃圾回收机制 的相关文章

  • 在Java中声明布尔变量的正确方法是什么?

    我刚刚开始学习Java 在我关注的在线课程中 我被要求尝试以下代码 String email1 email protected cdn cgi l email protection String email2 email protected
  • FileOutputStream (Apache POI) 保存时间过长

    当我使用 Apache poi 编辑 xlsx 文件时 保存时间太长 xlsx 文件包含公式格式设置和冻结窗格 我正在使用以下代码 try FileInputStream file new FileInputStream new File
  • 如何解决这个java.lang.RuntimeException?

    Google 开发者控制台显示我的应用程序在过去一个月中收到了两个相同的错误 但是这个RuntimeException没有指定错误源自的类或文件 我看不出什么具体的东西 以下是两种不同设备的错误 三星 Galaxy S8 Active cr
  • 如何使用 Spring 在 Postgresql 中存储 java.util.ArrayList

    我正在尝试批量插入一组 Bean bean 的属性之一是 ArrayList 批量更新失败 异常 Can t infer the SQL type to use for an instance of java util ArrayList
  • 相对文件路径问题

    我正在开发一个尝试读取配置文件的 portlet 我正在 eclipse 项目中开发它 我目前将配置文件放置在 WEB INF 文件夹 位于 root WEB INF 中 中 其名称为 config properties 如何使用 java
  • 使用 Java 查找句子中的确切单词

    我正在编写一个代码来识别文本中的国家 地区名称 我正在使用一本包含国家名称的字典India America Sri Lanka 我目前正在使用text contains key with key从字典中 然而 即使对于像这样的字符串 这也会
  • 没有名为 EntityManager 的持久性提供程序

    我有我的persistence xml使用相同的名称TopLink在下面META INF目录 然后 我的代码使用以下方式调用它 EntityManagerFactory emfdb Persistence createEntityManag
  • LinkedHashMap 的 ConcurrentModificationException

    不确定是什么触发了java util ConcurrentModificationException当我迭代时LinkedHashMap下面代码中的结构 使用Map Entry方法效果很好 从之前的帖子中没有得到关于触发此问题的良好解释 任
  • 哪种语言(在 JVM 上运行)最适合创建 DSL?

    我们需要创建复杂的固定长度和可变长度字符串 这些字符串可能代表客户资料 订单等 你们建议使用哪种基于 JVM 的编程语言 想法是让最终用户使用此 DSL 创建字符串 所以我正在寻找验证 代码完成等 Groovy http docs code
  • HQL(Hibernate)如何检查一个元素列表是否是另一个列表的子集?

    我很难创建一个 HQL 查询来检查表 X 的记录 a 列表是否包含在同一表 X 的另一个列表 b 中 这是我正在使用的一个例子 select r from Role r where select p from Permission p wh
  • 坚持/提交在 Spring JPA JUnit 的测试环境中不起作用

    我正在尝试设置基本的 JPA 插入测试 但数据库中没有保存任何内容 数据库是Postgresql Hibernate 用作持久性提供者 提前谢谢了 Entity public class Currency Id GeneratedValue
  • 更广泛的递归/泛型问题

    根据提出的问题和回答的问题here https stackoverflow com questions 6650532 recursive java generics between two classes 我有第二个 更复杂的一个 至少在
  • Java 和 C/C++ 之间进程间通信的最快(低延迟)方法

    我有一个Java应用程序 通过TCP套接字连接到用C C 开发的 服务器 应用程序和服务器都在同一台机器 Solaris 机器 上运行 但我们最终正在考虑迁移到 Linux 交换的数据类型是简单消息 登录 登录ACK 然后客户端请求某些内容
  • Ant JUnit ClassNotFoundException

    我意识到有很多类似的问题this one https stackoverflow com questions 10658636 new to ant classnotfoundexception with junit 但是在阅读了其中的大多
  • Java 从基本构造函数调用基本方法

    如何从 Super Super 调用 Super printThree 在下面的示例中 我改为调用 Test printThree class Super Super printThree I want Super printThree h
  • java jar 的清单属性

    在您的帮助下 我完成了我的第一个 Java 项目 现在我想创建一个 jar 并从 jar 运行应用程序 Java 项目 它是一个普通的控制台应用程序 它有另一个项目 控制台应用程序 作为依赖项 我通过右键单击 导出 创建一个 jar 使用
  • 绑定用户实体和 GlassFish 主体

    我有一个实体类User其中包含用户名 名字 姓氏和密码等信息 我有 GlassFish 3 1 服务器设置来执行身份验证 到目前为止 一切都很好 在容器对用户进行身份验证后 我需要某种方法将主体绑定到实际的用户实体 毕竟 GlassFish
  • 如何从图片中获取经纬度信息

    如何从设备或SD卡中的图片存储中获取经纬度信息 我找到了这个问题的非常简单的解决方案 所以我将其发布在这里以帮助像我一样有问题的朋友从图片中获取地理位置 Bundle bundle getIntent getExtras if null b
  • 在 Android 中使用 Asynctask 显示进度条

    我正在尝试显示进度条 我是一名安卓初学者 当我按下按钮时 任务应该在后台运行 但它不显示进度栏 什么是问题 我无法理解 请帮我 主要活动 package com example shikkok services import java ut
  • 如何从java类调用python脚本[重复]

    这个问题在这里已经有答案了 我有一个 java web 应用程序 我需要使用一个简单的网络爬虫从网页中读取 html 我在java中找不到任何简单的解决方案 但得到了一个非常简单的 python 脚本来解决我的问题 现在如何从我的 java

随机推荐

  • 【背包问题】之01背包和完全背包

    文章目录 1 01 背包 1 1 题目描述 1 2 基本思路 1 3 空间上的优化 1 4 算法实现 1 5 递归版本 1 6 按照递归修改的动态规划版本 1 7 总结 2 完全背包 2 1 题目描述 2 2 基本思路 2 3 优化一下 2
  • C语言:冒泡排序法:将若干字符串按字母顺序(由小到大)排序输出

    include
  • 大二上详细计划(量化到周)

    目录 前言 统筹安排 每周量化 每周进度 总体 花絮 前言 1 思来想去 决定对大二上的四个月进行一个安排 量化每周任务 具体到一本书看多少页 一套视频学多少 每个节点任务完成度 2 我们都是思想上的巨人 行动上的矮子 各种各样的欲望会阻碍
  • SpringCloud:Gateway之StripPrefix使用

    StripPrefix 过滤配置 很多时候也会有这么一种请求 用户请求路径是 api goods 而真实路径是 goods 这时候我们需要去掉 api才是真实路径 此时可以使用StripPrefix功能来实现路径的过滤操作 如下配置 ser
  • c语言时间序列预测,2.5.2 扩展案例:预测离散值时间序列

    2 5 2 扩展案例 预测离散值时间序列 假设我们观察到取值为0或1的数据 每个时刻一个值 为了了解具体应用 假设这是每天的天气数据 1代表有雨 0代表没有雨 假设已经知道最近几天是否下雨 我们希望预测明天是否会下雨 具体而言 对于某个k值
  • C++指针

    指针是一个存放内存地址的变量 通过指针 可以间接操作其它变量 指针的常用操作 int a 0 定义一个变量 int p a 定义一个指针 并指向a p 1 通过指针间接操作a 此时a 1 注意 p的类型是int 访问区域为4字节 Ps in
  • Revit二次开发--过滤对象(Revit 2014)

    1 获取元素的ID 通过UIDocument的Selection属性获取当前视图中选中的元素的ID 类型 using System using System Collections Generic using System Linq usi
  • QT - QML 遇到 module “QtQuick.Controls“ version 2.5 is not installed 的相关问题的解决策略

    问题由来 在跟着视频敲代码时 需要用到 DelayButton 这个控件 因此需要导入相关的库模块 跟着视频敲的是import QtQuick Controls 2 5 但可能由于版本较低的原因没有安装这个库模块 根据输入提示 有个 imp
  • STM32F407的CAN通信实验CAN1CAN2的设置

    CAN2的初始化参照上一篇博文就OK了 需要修改的地方 配置过滤器 CAN FilterInitStructure CAN FilterNumber 14 那为什么要修改额 查datasheet 双 CAN CAN1 主 bxCAN 用于管
  • Flex应用程序启动详解

    编写一个简单的Flex应用程序并不复杂 就算你从来没接触过Flex程序设计 照着帮助的实例步骤 不需花多长时间也能做出一个漂亮简捷的小程序出来 不过 随着对Flex程序编写的深入 会越来越觉得 其实要编写一个好的Flex应用程序并不简单 涉
  • uniapp切片-可视化设计工具(一套代码编译到7个平台iOS、Android、H5、小程序)

    uni app 是一个使用 Vue js 开发跨平台应用的前端框架 开发者编写一套代码 可编译到iOS Android H5 小程序等多个平台 一套代码编到7个平台 难以置信吗 依次扫描7个二维码 亲自体验最全面的跨平台效果 uni app
  • C++之sort()函数详解,刷题必备~

    顾名思义 sort就是用来排序的函数 它根据具体情形使用不同的排序方法 效率较高 一般来说 不推荐使用C语言中的qsort函数 原因是qsort用起来比较烦琐 涉及很多指针的操作 而且sort在实现中规避了经典快速排序中可能出现的会导致实际
  • C# 中的sealed修饰符学习

    转载原地址 http developer 51cto com art 200908 147327 htm C 语言还是比较常见的东西 这里我们主要介绍C sealed修饰符 包括介绍两个修饰符在含义上互相排斥用于方法和属性等方面 C sea
  • python爬虫网络出错怎么办_Python爬虫异常处理

    100 继续 客户端应当继续发送请求 客户端应当继续发送请求的剩余部分 或者如果请求已经完成 忽略这个响应 101 转换协议 在发送完这个响应最后的空行后 服务器将会切换到在Upgrade 消息头中定义的那些协议 只有在切换新的协议更有好处
  • linux上redis常用命令以及遇到的问题

    1 在linux上解压缩后使用make命令进行编译的时候 错误类型 zmalloc h 50 31 致命错误 jemalloc jemalloc h 没有那个文件或目录 原因是因为编译的时候Linux默认内存分配器是jemalloc 而Re
  • 添加商品到购物车 Vuex

    商品详情 购物车页面 code
  • OFDM插入导频过程详解

    ofdm符号的长度 有效数据 cp的长度 cp就是将有效数据的后半部分1 4截取并添加到有效数据的开始部分 比如一个ofdm符号的长度为4us 那么有效数据的长度为3 2us cp的长度为0 8us 子载波的间隔 1 有效数据的长度 就是有
  • Unity使用c#开发遇上的问题(十三)(unity平台下使用 Vuforia 以及 ARFoundiation 的总结,根据个人观点)

    文章目录 前言 一 Vuforia的使用感觉 二 ARfoundiation的使用感觉 总结 前言 有一段时间没有更新系列的内容 上次更新完又重新思考了一下以后进行的方向 这里就目前接触的Vuforia 和 unity 自带的AR 之前叫A
  • 自动生成根据mysql表创建hive表脚本

    bin bash source etc profile 该脚本为手动传参根据MySQL表信息创建hive表 输入参数判断逻辑 必须数据两个参数 一个是MySQL库名 第二个是表名 if eq 2 then db name 1 mysql 库
  • 浅析java垃圾回收机制

    一 什么是垃圾回收 1 垃圾回收 顾名思义 便是将已经分配出去的 但却不再使用的内存回收回来 以便能够再次分配 在 Java 虚拟机的语境下 垃圾指的是死亡的对象所占据的堆空间 垃圾回收只会负责释放那些对象占有的内存 此时对象也就被销毁 2