【JVM】垃圾回收 ——自问自答2

Q: System.gc() 的理解

System.gc()底层调用的是 Runtime.getRuntime.gc(),会现实出发FullGC。

但是,它的调用附带一个免责声明,无法保证对垃圾收集器的调用。

Q: 内存溢出和内存泄漏?

内存溢出: 简而言之,内存不够用了
可能因为堆内存在设置大小的时候 -Xms ,-Xmx 设置的比较小
前面也提到,虚拟机栈可以动态扩容时,当物理内存空间不足以给栈扩容,也会导致OutofMemory:stack
在jdk不同版本之中,方法区所产生的OOM是不同的。
jdk7及以前,是永久代 permgen space,而jdk8之后则是 Metaspace

一般情况下,在系统抛出OOM之前,GC会进被触发,尽可能清理出空间给新对象。
比如软引用就是在内存不足的情况下,会被触发回收。


内存泄漏(memory Leak)
当一个对象不会再被程序用到了,但是GC有不能回收他们,此时称之为内存泄漏。(一个不再被使用的对象,仍然有GC roots引用)

内存泄漏的举例:

1、单例模式。
首先明白一个问题,一个JVM对应的是一个进程(有一个与之对应的单例对象 Runtime),
平时说的微服务也好,分布式也好,不管怎样,请搞清楚。一个java进程,对应一个JVM,或者可以理解为,一个运行起来的服务,它就是一个进程。
如果在这个服务(进程)中,有一个单例对象,那么此对象的生命周期是随着JVM进程的消亡而消亡的。
如果此时单例对象内强引用了一个其他对象,而没有手动释放,那么这个被引用的对象的生命周期会和引用它的单例对象一样,一直随着JVM进程结束,才能结束。
如果这个被引用的对象后续不再被使用,但是它无法被GC销毁,这时候,就是个典型的内存泄漏场景。
我们可以用软引用来解决这种问题。

2、没用关闭某些资源
java的面向对象思想,把很多资源使用场景都有一个建立链接和关闭链接的过程,这个其实是一种网络分层模型中,提供可靠服务的前提。
比如数据库链接,套接字链接(socket),IO,他们都是要进行手动close的。前两个其实都是基于TCP的建立连接和关闭链接的过程。


Q: 谈一谈Stop the World

STW GC线程在工作的过程中,与用户线程是并发执行的,二者抢占CPU资源,GC执行,用户线程被暂停。
 
 可达性分析算法中枚举根节点会导致Java执行线程停顿。
 因为: 分析工作要保证一致性结果,一般是在当前进程快照中分析
 如果分析过程中,一直有用户线程在执行,就会导致分析结果不准确。
 
 (开发中尽量少使用System.gc 会产生STW)
 
 
 
 
 
 Q: 垃圾回收的并行,并发。
 
 垃圾回收事件的并行与串行是对立的,它描述的是垃圾收集线程的工作关系。
 串行,指在进行垃圾收集时,只有一个GC线程在工作。
 并行:指在进行垃圾收集时,有多个GC线程在同时工作。
 注意上述两个场景中,用户线程都是暂停的,并行与串行机制只是在描述垃圾收集线程。
 
 但是请注意一点:并行,虽说是要建立在多处理器条件下,才可能发生的,但是在操作系统相关的知识体系中,“并行”的概念并不是绝对的。
 因为并行的垃圾回收行为,在单处理器环境下,是通过并发执行表现的。但是请注意发生CPU争抢的,只有GC线程而没有用户线程。
 
 这个道理其实就像理解操作系统的共享特性。共享分为独占式共享,和同时共享。
 独占式共享,就是串行的,一个作业完成对资源的使用后,再运行下一个作业去访问资源。
 但是同时访问共享,并不真是"同时访问",本质上来说,也是通过并发的特性来实现"同时"。
 
 
 
 垃圾收集的并发行为:
 
指的是垃圾收集线程,可以和用户线程 "同时"执行(这里的同时,和上面的解释是一样的,还是取决于CPU和工作线程的个数)

因此,垃圾收集上下文环境所说的并发和并行,和操作系统层面说的并发,并行是有区别的。

Q: 安全区和安全点
程序执行时并不是在任何地方都能停下来开始GC,只是在特定位置才能停顿下来,开始GC,这些位置称为 安全点

安全点的选择一般是以"是否具有让程序长时间执行的特征",比如选择一些执行时间较长的指令作为安全点,比如方法调用,循环跳转和异常跳转。

如何在GC发生时,检查所有线程都跑到了最近的安全点停顿下来呢?
1、抢占式中断:弃用
2、主动式中断:设置标志位,各个线程运行到Safepoint,主动轮训这个标志,若中断标志为真,将自己进行中断挂起。

这里补充一个操作系统的知识

进程在执行的过程时,CPU会有内核态和用户态,当发生系统中断,CPU会从用户态转换为内核态,使操作系统夺回CPU控制权(也是唯一途径)
内核态->用户态:执行一条特权指令----修改PSW的标志位为用户态。操作系统让出CPU使用权。
用户态->内核态:由 中断 引发,硬件自动完成变态过程。
中断分为 内中断和外中断,一般程序执行遇到异常,或请求系统调用,执行访管指令都属于内中断。
当进入中断时,用户进程根据不同场景会进入就绪,阻塞,就绪/阻塞挂起,退出等状态。

操作系统关于线程实现方式有三类:内核级线程、用户级线程、组合方式

用户级线程:(图片来自王道,侵删)

早期,操作系统只支持进程,没用线程的概念,内核中只有进程的概念,进程作为资源分配的单位,
用户通过线程库来对一个进程进行拆分执行。最简单的线程库,可以理解为:

int main(){int flag =0;while(true){if(flag==0){do A;}if(flag==1){do B;}if(flag==3){do C;}}}

用户线程是建立在用户空间的线程库上,系统内核不感知线程存在的实现,用户线程的创建、同步、销毁和调度完全在用户状态中完成。
但是这种设计的时间片划分仍然是以进程为单位的,进程A有一个线程,进程B有100个线程,假设两者的时间片长度相同,这种分配结果是不公平的。
而且,某一线程被阻塞,整个进程都会被阻塞,内核分配CPU资源也是按进程分配,也就是说进程B中的所有线程都是并发执行,每次只能执行1个线程。


内核级线程

操作系统内核支持的线程,这种线程有内核来完成线程切换。每个线程都有自己的TCB
换句话说,操作系统内核已经支持线程的概念了,内核已经将线程作为最小的资源分配单位。


用户线程的实现是通过线程库来创建管理的,线程库分为有内核支持和无内核支持,区别在于在调用库内函数时,是否需要进行内核的系统调用。
java线程库就是常用的线程库之一。它以来与宿主系统的线程库,windows上是 windows API,Unix上是POSIX pthreads。

这些模型是建立在支持内核级线程的系统中的:

多线程模型
用户线程和内核线程链接方式不同,分为一对一,多对一,多对多。

一对一:一个用户线程对应一个内核线程,用户线程被阻塞,并不会影响其他线程的运行。
并发能力较强,一个线程阻塞,并不会影响到其他线程,但是一一对应开销也很大。(见上图)

多对一:一个内核线程对应多个用户线程,这些线程一般属于一个进程,线程的调度和管理都是在用户空间完成的(执行效率比较高)。
缺点很突出:任意时刻,只能有一个线程与内核线程进行映射,一个线程阻塞,整个进程会发生阻塞,多个线程不能同时在多个处理器上运行。

java每个线程都对应了一个本地线程,其实java的线程是在JVM虚拟机中通过一些C++写的方法调用,来调用本地线程库的API,对线java程状态进行管理,映射。
所有这个对应的本地线程,实际上是本地线程库中的用户级的线程,而非内核线程,至于本地线程库到底使用了那种多线程模型,要具体系统具体分析,这也是JVM实现跨平台的一个手段。

这里补充这些知识,是想说,用户线程在安全点的STW,其受到中断而挂起,其实是通过

JVM——本地线程库——内核级线程状态切换  这一套执行流程的。这个安全点造成的中断,并非操作系统里说的中断,OS里的中断粒度是针对进程来说的。

安全区:

如果某些线程在准备进入安全点之前,是阻塞态,该线程此时是无法响应JVM的中断请求的,运行到安全点,再中断挂起,
安全区是一段代码片段中,对象的引用关系没有发生变化,再这个区域中任何位置开始GC都是安全的。
从一个点 被扩大成了一个片段。

执行过程:
当线程运行到safe Region代码段时,首先标识已经进入了safe Region,若这段时间内发生GC,JVM会忽略标识为 safe Region状态的线程。

当线程即将离开safe Region时,会检查JVM是否已经完成GC,若完成了,则继续运行,否则线程必须等待到收到可以安全离开safe Region的信号为止。

Q: 强软弱虚来一套

强引用:普通创建对象的语法,都是强引用。
软引用:堆内内存不足时,软引用会被回收
弱引用:发生垃圾回收行为时,一定会被回收
虚引用:一个对象是否有虚引用存在,跟其生存时间没叼毛影响,无法通过一个虚引用获取一个对象实例。
设置虚引用的目的在于垃圾回收该对象时,得到一个系统通知。它其实可以理解为一个对象回收的跟踪。对象回收后,将虚引用加入引用队列,以通知程序该对象的回收情况

//-xms9m -xmx9M  -XX:+PrintGCDetailsclass ReferenceDemo{//强引用,ReferenceDemo对象实例化后,objRf_inheap位于实例对象所在的堆空间中Object objRf_inheap =new Object();public void foo(){//强引用,引用存在于局部变量表中的第二个位置,slot标号为1 Object objRf_inLV =new Object();//软引用,当内存空间不足的时候,会在GC中对其进行回收Object obj =new Object();SoftReference obj_softRf =new SoftReference<Object>(obj);obj=null;//可以获取代到软引用包装的对象obj_softRf.get();//创建一个大对象,当前堆装不下了,目的是要触发GC,堆内内存不足时,软引用会被回收byte[] buffers =new byte[7*1024*1024];....
}@Override
protected void finalize() throws Throwable {super.finalize();System.out.println("我被调用了呀!!!!");
}
}

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

windows为nginx添加定时任务(开机延迟启动)

windows开机启动任务 调用定时任务管理器选中windows创建基本任务设置名称和描述设置触发器 并且添加个延迟触发设置操作设置条件配置设置 调用定时任务管理器 winr 输入 taskschd.msc回车 选中windows创建基本任务 设置名称和描述 设置触发器 并且添加个延迟触发 设置操作 …

Aligning Large Language Models with Human: A Survey

本文也是LLM相关的综述文章&#xff0c;针对《Aligning Large Language Models with Human: A Survey》的翻译。 对齐人类与大语言模型&#xff1a;综述 摘要1 引言2 对齐数据收集2.1 来自人类的指令2.1.1 NLP基准2.1.2 人工构造指令 2.2 来自强大LLM的指令2.2.1 自指令2.2.2 …

离散 Hopfield 神经网络的分类与matlab实现

1 案例背景 1.1离散 Hopfield 神经网络学习规则 离散型 Hopfield神经网络的结构、工作方式,稳定性等问题在第9章中已经进行了详细的介绍,此处不再赘述。本节将详细介绍离散Hopfield神经网络权系数矩阵的设计方法。设计权系数矩阵的目的是: ①保证系统在异步工作时的稳…

6.s081/6.1810(Fall 2022)Lab5: Copy-on-Write Fork for xv6

前言 本来往年这里还有个Lazy Allocation的&#xff0c;今年不知道为啥直接给跳过去了。. 其他篇章 环境搭建 Lab1: Utilities Lab2: System calls Lab3: Page tables Lab4: Traps Lab5: Copy-on-Write Fork for xv6 参考链接 官网链接 xv6手册链接&#xff0c;这个挺重要…

开发运营监控

DevOps 监控使管理员能够实时了解生产环境中的元素&#xff0c;并有助于确保应用程序平稳运行&#xff0c;同时提供最高的业务价值&#xff0c;对于采用 DevOps 文化和方法的公司来说&#xff0c;这一点至关重要。 什么是开发运营监控 DevOps 通过持续开发、集成、测试、监控…

vscode 第一个文件夹在上一层文件夹同行,怎么处理

我的是这样的 打开终端特别麻烦 解决方法就是 打开vscode里边的首选项 进入设置 把Compact Folders下边对勾给勾掉

Java Set集合:HashSet和TreeSet类

Set 集合类似于一个罐子&#xff0c;程序可以依次把多个对象“丢进”Set 集合&#xff0c;而 Set 集合通常不能记住元素的添加顺序。也就是说 Set 集合中的对象不按特定的方式排序&#xff0c;只是简单地把对象加入集合。Set 集合中不能包含重复的对象&#xff0c;并且最多只允…

谈谈DNS是什么?它的作用以及工作流程

作者&#xff1a;Insist-- 个人主页&#xff1a;insist--个人主页 作者会持续更新网络知识和python基础知识&#xff0c;期待你的关注 目录 一、DNS是什么&#xff1f; 二、DNS的作用 三、DNS查询流程 1、查看浏览器缓存 2、查看系统缓存 3、查看路由器缓存 4、查看ISP …

【JavaEE】深入了解Spring中Bean的可见范围(作用域)以及前世今生(生命周期)

【JavaEE】Spring的开发要点总结&#xff08;4&#xff09; 文章目录 【JavaEE】Spring的开发要点总结&#xff08;4&#xff09;1. Bean的作用域1.1 一个例子感受作用域的存在1.2 通过例子说明作用域的定义1.3 六种不同的作用域1.3.1 singleton单例模式&#xff08;默认作用域…

【C++】C++11 新特性总结 | C++ 常见设计模式总结(秋招篇)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言介绍几种C11新特性介绍一下自动类型推导auto和decltype关键字的用法举例讲一下范围基于的for循环介绍一下列表初始化讲一下右值引用&#xff0c;和左值引用的区…

51单片机(普中HC6800-EM3 V3.0)实验例程软件分析 实验三 LED流水灯

目录 前言 一、原理图及知识点介绍 二、代码分析 知识点五&#xff1a;#include 中的库函数解析 _crol_&#xff0c;_irol_&#xff0c;_lrol_ _cror_&#xff0c;_iror_&#xff0c;_lror_ _nop_ _testbit_ 前言 第一个实验:51单片机&#xff08;普中HC6800-EM3 V3.0…

数据结构——红黑树基础(博文笔记)

数据结构在查找这一章里介绍过这些数据结构&#xff1a;BST&#xff0c;AVL&#xff0c;RBT&#xff0c;B和B。 除去RBT&#xff0c;其他的数据结构之前的学过&#xff0c;都是在BST的基础上进行微小的限制。 1.比如AVL是要求任意节点的左右子树深度之差绝对值不大于1,由此引出…

H263压缩码流如何分解为一个一个单元并查询到其宽高?

H263码流尺寸规格有限&#xff0c;只有以下几种&#xff1a; H263码流有四个分层&#xff1a; 1、图像层 2、块组 3、宏块 4、块 下面分别介绍&#xff1a; 具体介绍如下&#xff0c;5.1.3中红色框选部分就是压缩码流的宽高指示&#xff1a; 图像层 上面就是H263的图像层&am…

P1156 垃圾陷阱(背包变形)

垃圾陷阱 题目描述 卡门――农夫约翰极其珍视的一条 Holsteins 奶牛――已经落了到 “垃圾井” 中。“垃圾井” 是农夫们扔垃圾的地方&#xff0c;它的深度为 D D D&#xff08; 2 ≤ D ≤ 100 2 \le D \le 100 2≤D≤100&#xff09;英尺。 卡门想把垃圾堆起来&#xff0c…

智慧水利整体解决方案[43页PPT]

导读&#xff1a;原文《智慧水利整体解决方案[43页PPT]》&#xff08;获取来源见文尾&#xff09;&#xff0c;本文精选其中精华及架构部分&#xff0c;逻辑清晰、内容完整&#xff0c;为快速形成售前方案提供参考。 完整版领取方式 完整版领取方式&#xff1a; 如需获取完整的…

概念解析 | 生成式与判别式模型在低级图像恢复与点云重建中的角力:一场较量与可能性探索

注1:本文系“概念解析”系列之一,致力于简洁清晰地解释、辨析复杂而专业的概念。本次辨析的概念是:生成式模型与判别式模型在低级图像恢复/点云重建任务中的优劣与特性。 生成式与判别式模型在低级图像恢复与点云重建中的角力:一场较量与可能性探索 1. 背景介绍 机器学习…

elasticSearch常见的面试题

常见的面试问题 描述使用场景 es集群架构3个节点&#xff0c;根据不同的服务创建不同的索引&#xff0c;根据日期和环境&#xff0c;平均每天递增60*2&#xff0c;大约60Gb的数据。 调优技巧 原文参考&#xff1a;干货 | BAT等一线大厂 Elasticsearch面试题解读 - 掘金 设计阶…

C++QT教程2——创建QT项目

文章目录 2 创建Qt项目2.1 使用向导创建2.2 手动创建2.3 .pro文件2.4 一个最简单的Qt应用程序main入口函数中&#xff08;main.cpp&#xff09;arnold_widget.h函数arnold_widget.cpp 参考文章 2 创建Qt项目 2.1 使用向导创建 打开Qt Creator 界面选择 New Project或者选择菜…

SAP MM学习笔记15-物料调达中的Master数据(2)-品目Master

SAP中做一个购买发注的时候&#xff0c;涉及到以下Master数据&#xff1a; 1&#xff0c;仕入先Master&#xff08;供应商&#xff09;&#xff1a;跟谁买 2&#xff0c;品目Master&#xff08;物料&#xff09;&#xff1a;买什么 3&#xff0c;购买情报&#xff1a;什么价…

Python selenium对应的浏览器chromedriver版本不一致

1、chrome和chromedriver版本不一致导致的&#xff0c;我们只需要升级下chromedriver的版本即可 浏览器版本查看 //打开google浏览器直接访问&#xff0c;查看浏览器版本 chrome://version/ 查看chromedriver的版本 //查看驱动版本 chromedriver chromedriver下载 可看到浏…