JVM7:垃圾回收是什么?从运行时数据区看垃圾回收到底回收哪块区域?垃圾回收如何去回收?垃圾回收策略,引用计数算法及循环引用问题,可达性分析算法

垃圾回收是什么?从运行时数据区看垃圾回收到底回收哪块区域? 垃圾回收如何去回收? 垃圾回收策略 引用计数算法及循环引用问题 可达性分析算法

  • 垃圾回收是什么?从运行时数据区看垃圾回收到底回收哪块区域?
    • 垃圾回收如何去回收?
      • 垃圾回收策略
    • 引用计数算法及循环引用问题
    • 可达性分析算法
  • 思考
  • 汇总

垃圾回收如何去回收?
垃圾回收策略
引用计数算法及循环引用问题
可达性分析算法)

垃圾回收是什么?从运行时数据区看垃圾回收到底回收哪块区域?

请添加图片描述
JVM内存模型认识的差不多了,就应该思考,什么样的内存模型适合什么样的GC策略,包括垃圾回收为什么会出现。实际上,很多东西都是相对应版本的JVM强加上去的。那么垃圾回收是什么?到底回收哪块区域?如何去回收?

这个时候观察运行时数据区来进行分析。
线程私有的区域是完全没有必要回收的,因为方法消亡就消亡了,它的生命周期很短,会伴随着你的方法的退出而消亡,因此不必关心它的回收,而且类文件结构确定之后,就知道整个方法当中字节码指令流转的一个情况了,所以不需要对这块区域进行关心。

线程共享的区域是方法区和堆这两块区域,而方法区MetaSpace中,实际上它的回收有没有呢?有的,但是很少,或者说回收的效率并不高,因为方法区当中的数据是静态变量,常量,字符串常量池,类信息,即时编译后的代码,它的生命周期一般都很长,随着程序运行一段时间之后,它占用方法区的那一块内存会趋于稳定,因为这些东西不回收,所以回收重点关注的地方还是这个区域。因为Java是一门面向对象的一门高级语言,所以对象的创建以及回收才是最重要的。而我们的GC,或者说所谓的垃圾回收,更多的是对于堆内存这块区域的回收,来进行讨论。

那么堆要进行回收的话,到底要怎么去进行回收呢?

垃圾回收如何去回收?

首先需要考虑的第一个问题:什么样的场景下适合使用什么样的垃圾回收策略。
这里注意策略和算法是不一样的,算法是真正落地的实现,而策略不一定要落地。

回收策略按照我们的思想去设计优化的话,首先肯定要关注内存的使用情况,因为垃圾回收本身就是一种穷人策略,因为没有那么多内存共我们去挥霍,所以才会想尽办法提高我们垃圾回收的效率。

垃圾回收策略

  • 收的多: 收的多,意味着收的久。尽可能每次多回收一些对象,尽可能多腾出一些内存,而收的多意味着收的久。
  • 收的快: 收的快,意味着每次收的少需要多次回收。最好可以将时间缩短到一次网络延迟,哪怕回收次数很多都可以容忍,这样收再多次都是无所谓的。

因此会在垃圾回收的时间上和CPU的效率上有个抉择,假设CPU使用率过高,那么可以尽可能的去调低垃圾回收的一个频率,使得CPU的使用率能够在我们接受的范围内,也就是可控性回收

比如我们平时收拾屋子,那么首先就是确定屋子多大,然后哪些东西是垃圾。程序亦是如此,hotsport的开发者也会有这样的想法,它需要有一套判断当前对象是垃圾的依据(或者叫算法)。那么在程序当中,所有的执行逻辑、判断逻辑都可以称之为算法,因为程序就是逻辑+数据组成的。

为什么回收选取操作性较高的数据?
举个例子,你在家里扫垃圾,肯定也是选择比较容易清理的哪些东西叫做垃圾,不好拿的和好拿的肯定先选好拿的。那么在当前的场景中,我们操作性较高的数据是对象,因此是根据对象去进行一个讨论。

而在Java中,引用和对象显然是有关联的,如果要操作对象,必然是会引用来去执行,那么这个时候,最显然的一个办法就是通过引用计数来判断对象是否可以回收,简单的来说,如果一个对象没有任何与之相关联的引用,即它们的引用计数都为0的情况下,也就是说,这个对象没有任何场景下可能会使用到它了,那这个对象就是可回收对象,这就是引用计数法。但是现在Java主流算法并不是这个,因为它难以解决循环引用的问题。

引用计数算法及循环引用问题

/**
 * 引用计数法难以解决循环引用问题
 */
public class CircularReferenceDemo {

    public static void main(String[] args) {

        CircularReferenceObject obj1 = new CircularReferenceObject();
        CircularReferenceObject obj2 = new CircularReferenceObject();
        /**
         * 这两句代码表示:
         * 第一步:虚拟机栈有两个东西obj1、obj2,它是虚拟机栈中的局部变量表中的元素
         * 第二步:new两个CircularReferenceObject对象,这两个对象是不同的CircularReferenceObject实例,在堆当中共开辟两个内存地址
         * 第三步:obj1指向堆中的实例1,obj2指向堆中的实例2
         *
         * 此时此刻,堆中的这两个实例的引用计数应该各自+1=1
         */

        obj1.instance = obj2;
        obj2.instance = obj1;
        /**
         * 让堆中的两个实例互相引用,obj1指向obj2,obj2指向obj1
         *
         * 此时此刻,堆中的这两个实例的引用计数应该各自再+1=2
         */

        obj1 = null;
        obj2 = null;
        /**
         * 赋值为null,表示不再指向任何数据,即栈中元素不再指向堆中实例
         *
         * 此时此刻,堆中的这两个实例的引用计数应该各自-1=1
         *
         * 这个时候,循环引用问腿就来了:按照引用计数法,堆中这两个实例各自的引用计数都不为0,也就是说这两个实例所占用的堆内存空间无法释放
         *
         * 系统给到实例内存空间但是无法释放的这种情况称之为内存泄露,如果这种情况一直发生,最终会导致内存溢出,因此主流的JVM已经摒弃了这种算法
         */
    }

    static class CircularReferenceObject {
        public Object instance = null;
    }
}

请添加图片描述
对于对象之间的循环引用问题,其实引用计数法它会有策略进行解决,但是这个不是Java应该关心的事情。Java中已经摒弃了引用计数法这种算法,python还在用,引用计数法这种算法的效率会比另一种算法快的多,既然主流的JVM已经摒弃了这种算法,那么必然会出现一种新的算法对它进行替代,来解决循环引用的问题,最少也是让所谓循环引用的问题带来的影响没那么大,那么另一种算法横空出世,就是可达性分析算法。

可达性分析算法

可达性分析算法,也被称为根搜索算法,目前主流的JVM都是采用的这种算法,比如Sun公司的hotsport。
这个算法的核心是从所谓的GC root进行出发,也就是从一个所谓的根进行出发,利用数学中的图论(Graph Theory)知识,从根触发,单条引用链能够到达的对象,便是存活对象,反之即为不可达对象,不可达对象就是需要回收的垃圾。

这里面涉及到两个概念根(所谓的GC root)和可达性。所谓的根、GC root只是一种引用,它并不是对象,它只是告诉你地址,让你知道如何找对象。

哪些可以作为GC root的对象?

  • 虚拟机栈中的局部变量表中的元素Object obj = new Object();,这种new出来的对象,必然是我们需要的对象,所以obj这种位于虚拟机栈中的局部变量表中的元素必然可以作为GC root
  • 方法区的静态变量以及常量
  • 本地方法栈JNI中的元素

思考

引用到底是什么?不同引用会有什么作用?不同引用会不会有不同的监控策略?如果可达性分析算法标记为不可达会立即进行垃圾回收吗?常说的标记整理又是做什么的?

汇总

JVM1:官网了解JVM;Java源文件运行过程、javac编译Java源文件、如何阅读.class文件、class文件结构格式说明、 javap反编译字节码文件;类加载机制、class文件加载方式

JVM2:类加载机制、class文件加载方式;类加载的过程:装载、链接、初始化、使用、卸载;类加载器、为什么类加载器要分层?JVM类加载机制的三种方式:全盘负责、父类委托、缓存机制;自定义类加载器

JVM3:图解类装载与运行时数据区,方法区,堆,运行时常量池,常量池分哪些?String s1 = new String创建了几个对象?初识栈帧,栈的特点,Java虚拟机栈,本地方法发栈,对象指向问题

JVM4:Java对象内存布局:对象头、实例数据、对齐填充;JOL查看Java对象信息;小端存储和大端存储,hashcode为什么用大端存储;句柄池访问对象、直接指针访问对象、指针压缩、对齐填充及排序

JVM5:JVM内存模型与运行时数据区的关系,堆为什么分区,分代年龄,Young区划分,Survivor区为什么分为S0和S1,如何理解各种GC:Partial GC、Full GC、Young GC

JVM6:JVM内存模型验证;使用visualvm查看JVM视图;Visual GC插件下载链接;模拟JVM常见错误,模拟堆内存溢出,模拟栈溢出,模拟方法区溢出

JVM7:垃圾回收是什么?从运行时数据区看垃圾回收到底回收哪块区域?垃圾回收如何去回收?垃圾回收策略,引用计数算法及循环引用问题,可达性分析算法

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/91866.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

详细手机代理IP配置

嗨,亲爱的朋友们!作为一家代理产品供应商,我知道有很多小伙伴在使用手机进行网络爬虫和数据采集时,常常会遇到一些IP限制的问题。别担心!今天我要给大家分享一下手机IP代理的设置方法,让你们轻松应对这些限…

基于Android水果蔬菜果蔬到家商城系统 微信小程序uniAPP的开发与实现

果蔬到家是商家针对用户必不可少的一个部分。在商铺发展的整个过程中,果蔬到家担负着最重要的角色。为满足如今日益复杂的管理需求,各类果蔬到家程序也在不断改进。本课题所设计的springboot基于HBuilder X的果蔬到家APP,使用SpringBoot框架&…

Nginx 高级配置

目录 1 网页的状态页 2 Nginx 第三方模块 2.1 ehco 模块 3 变量 3.1 内置 3.2 定义变量 4 Nginx压缩功能 5 https 功能 6 自定义图标 1 网页的状态页 基于nginx 模块 ngx_http_stub_status_module 实现,在编译安装nginx的时候需要添加编译参数 --with-http…

php开发websocket笔记(1)

1.运行server1.php文件 Windows命令行运行 php server1.php<?phperror_reporting(E_ALL); set_time_limit(0); //ob_implicit_flush(); $address 0.0.0.0;//可以监听网络上的请求 $address 127.0.0.1;//只能监听本机的请求$port 10005; //创建端口 $socket1 socket_cr…

win开机自启jar包

下载winsw工具 只需下载图中红框的工具 https://github.com/winsw/winsw/releases 文件配置 将下载的文件与jar文件放置在一起&#xff0c;两个文件名修改为服务名 编辑xml文件 注意不要出现中文&#xff0c; 标签内的jar文件地址要改为自己目录 <service><!-- I…

【JVM】运行时数据区域

文章目录 说明程序计数器虚拟机栈本地方法栈Java堆方法区运行时常量池直接内存 说明 Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域。这些区域有各自的用途&#xff0c;以及创建和销毁的时间&#xff0c;有的区域随着虚拟机进程的启动而一直…

【图论】缩点的综合应用(一)

一.缩点的概念 缩点&#xff0c;也称为点缩法&#xff08;Vertex Contraction&#xff09;&#xff0c;是图论中的一种操作&#xff0c;通常用于缩小图的规模&#xff0c;同时保持了图的某些性质。这个操作的目标是将图中的一些节点合并为一个超级节点&#xff0c;同时调整相关…

【Springboot】| 从深入自动配置原理到实现 自定义Springboot starter

目录 一. &#x1f981; 前言二. &#x1f981; Spring-boot starter 原理实现分析2.1 自动配置原理 三. &#x1f981; 操作实践3.1 项目场景3.2 搭建项目3.3 添加相关依赖3.4 删除一些不需要的东西3.5 发邮件工具类逻辑编写3.6 创建相关配置类3.7 创建 Spring.factories 文件…

【javaweb】学习日记Day7 - Mysql 数据库 DQL 多表设计

之前学习过的SQL语句笔记总结戳这里→【数据库原理与应用 - 第六章】T-SQL 在SQL Server的使用_Roye_ack的博客-CSDN博客 目录 一、DQL 数据查询 1、基本查询 2、条件查询 3、分组查询 &#xff08;1&#xff09;聚合函数 ① count函数 ② max min avg sum函数 &…

【Tkinter系列02/5】界面初步和布局

本文是系列文章第二部分。前文见&#xff1a;【Tkinter系列01/5】界面初步和布局_无水先生的博客-CSDN博客 说明 一般来说&#xff0c;界面开发中&#xff0c;如果不是大型的软件&#xff0c;就不必用QT之类的实现&#xff0c;用Tkinter已经足够&#xff0c;然而即便是Tkinter规…

基于大数据+django+mysql的银行信用卡用户的数仓系统

系统阐述的是银行信用卡用户的数仓系统的设计与实现&#xff0c;对于Python、B/S结构、MySql进行了较为深入的学习与应用。主要针对系统的设计&#xff0c;描述&#xff0c;实现和分析与测试方面来表明开发的过程。开发中使用了 django框架和MySql数据库技术搭建系统的整体架构…

gitcode中删除已有的项目

镜像地址&#xff1a; https://www.jianshu.com/p/504c1418adb7?v1693021320653 扩展阅读 如何在GitLab中删除一个项目 https://www.codenong.com/cs106866762/ 简介&#xff1a; 如何在GitLab中删除一个项目 最近GIT上建了太多项目。想清一下&#xff0c;就在网上查了查…

opencv-答题卡识别判卷

#导入工具包 import numpy as np import argparse import imutils import cv2# 设置参数 ap argparse.ArgumentParser() ap.add_argument("-i", "--image", requiredTrue,help"path to the input image") args vars(ap.parse_args())# 正确答案…

【动手学深度学习】--18.图像增广

文章目录 图像增广1.常用的图像增广方法1.1翻转和裁剪1.2改变颜色1.3结合多种图像增广方法 2.使用图像增广进行训练3.训练 图像增广 官方笔记&#xff1a;图像增广 学习视频&#xff1a;数据增广【动手学深度学习v2】 图像增广在对训练图像进行一系列的随机变化之后&#xff…

实验八 网卡驱动移植

【实验目的】 掌握 Linux 内核配置的基本方法&#xff0c;完成对网卡驱动、NFS 等相关功能的配置 【实验环境】 ubuntu 14.04 发行版FS4412 实验平台交叉编译工具&#xff1a;arm-none-linux-gnueabi- 【注意事项】 实验步骤中以“$”开头的命令表示在 ubuntu 环境下执行&…

21.2 CSS 三大特性与页面布局

1. 开发者工具修改样式 使用开发者工具修改样式, 操作步骤如下: * 1. 打开开发者工具: 在浏览器中右键点击页面, 然后选择检查或者使用快捷键(一般是 F12 或者 CtrlShiftI)来打开开发者工具.* 2. 打开样式编辑器: 在开发者工具中, 找到选项卡或面板, 一般是Elements或者Elemen…

最新AI系统ChatGPT程序源码/微信公众号/H5端+搭建部署教程+完整知识库

一、前言 SparkAi系统是基于国外很火的ChatGPT进行开发的Ai智能问答系统。本期针对源码系统整体测试下来非常完美&#xff0c;可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。 那么如何搭建部署AI创作ChatGPT&#xff1f;小编这里写一个详细图文教程吧&#xff01…

不系安全带抓拍自动识别

不系安全带抓拍自动识别系统通过yolo系列算法框架模型利用高清摄像头&#xff0c;不系安全带抓拍自动识别算法对高空作业场景进行监控&#xff0c;当检测到人员未佩戴安全带时会自动抓拍并进行告警记录。YOLO系列算法是一类典型的one-stage目标检测算法&#xff0c;其利用ancho…

一生一芯8——在github上添加ssh key

为在github上下载代码框架&#xff0c;这里在github上使用ssh key进行远程连接&#xff0c;方便代码拉取 参照博客https://blog.csdn.net/losthief/article/details/131502734 本机 系统ubuntu22.04 git 版本2.34.1 本人是第一次配置&#xff0c;没有遇到奇奇怪怪的错误&…

Faster RCNN网络数据流总结

前言 在学习Faster RCNN时&#xff0c;看了许多别人写的博客。看了以后&#xff0c;对Faster RCNN整理有了一个大概的了解&#xff0c;但是对训练时网络内部的数据流还不是很清楚&#xff0c;所以在结合这个版本的faster rcnn代码情况下&#xff0c;对网络数据流进行总结。以便…