JVM的内存模型和垃圾回收

JVM内存区域

内存模型图:


线程共享。所有的对象实例以及数组都要在堆上分配。回收器主要管理的对象。

它的目的是存放对象实例。同时它也是GC所管理的主要区域,因此常被称为GC堆,又由于现在收集器常使用分代算法,Java堆中还可以细分为新生代和老年代

Java堆可以存在物理上不连续的内存空间,就像磁盘空间只要逻辑是连续的即可。它的内存大小可以设为固定大小,也可以扩展。

主流的虚拟机如HotPot都能按扩展实现(通过设置 -Xmx和-Xms),如果堆中没有内存,完成实例分配,而且堆无法扩展将报OOM错误(OutOfMemoryError)


方法区

存储类对象

方法区是被所有线程共享的内存区域,用来存储已被虚拟机加载的类信息、常量、静态变量、JIT(just in time,即时编译技术)编译后的代码等数据。运行时常量池是方法区的一部分,用于存放编译期间生成的各种字面常量和符号引用。

什么是JIT-CSDN博客

通过反射获取到的类型、方法名、字段名称、访问修饰符等信息就是从方法区获取到的。在使用到CGLib对类进行增强时,增强的类越多,就需要越大的方法区类存储动态生成的Class信息,当存放方法区数据的内存溢出时,会报OutOfMemoryError异常。


栈区,在方法结束自动清空,又可细分为:

程序计数器

程序计数器,又叫PC寄存器,是一块很小的内存空间,它是线程私有的,可以认作为当前线程的行号指示器

程序计数器?

为了线程切换可以恢复到正确执行位置,每个线程都需有独立的一个程序计数器,不同线程之间的程序计数器互不影响,独立存储。

虚拟机栈

线程私有,生命周期与线程相同,就是我们平时说的栈,栈描述的是Java方法执行的内存模型。

每个方法被执行的时候都会创建一个栈帧用于存储局部变量表,操作栈,动态链接(对象的内存地址),方法出口(返回值的内存)等信息。每一个方法被调用的过程就对应一个栈帧在虚拟机栈中从入栈到出栈的过程。

本地方法栈(JVM执行本地方法)

本地方法栈是与虚拟机栈发挥的作用十分相似,区别是虚拟机栈执行的是Java方法(也就是字节码)服务,而本地方法栈则为虚拟机使用到的native方法服务,可能底层调用的c或者c++,我们打开jdk安装目录可以看到也有很多用c编写的文件,可能就是native方法所调用的c代码。

  • 动态链接: 每个栈帧都保存了 一个 可以指向当前方法所在类的 运行时常量池, 目的是: 当前方法中如果需要调用其他方法的时候, 能够从运行时常量池中找到对应的符号引用, 然后将符号引用转换为直接引用,然后就能直接调用对应方法, 这就是动态链接
  • 不是所有方法调用都需要动态链接的, 有一部分符号引用会在类加载解析阶段, 将符号引用转换为直接引用, 这部分操作称之为: 静态解析. 就是编译期间就能确定调用的版本, 包括: 调用静态方法, 调用实例的私有构造器, 私有方法, 父类方法

垃圾回收

Garbage Collection(GC)

判断对象已死

1.引用计数算法

引用计数算法是在对象中加入一个计数器,当对象被引用,计数器+1,当引用失效,计数器-1,当计数器的值编程0,就是没有任何一个变量来引用这个对象,那么这个对象就是垃圾

这种算法实现简单,效率高,但是有一个严重的问题会导致内存泄漏,那就是对象之间循环引用,比如说A对象持有B对象的引用,B对象持有A对象的引用,那么A和B的计数器值永远>=1,也就是说这两个对象永远不会被回收,这是一堆垃圾。

内存溢出:指程序在运行过程中,因为申请的内存超过了可用的内存空间而导致程序崩溃或异常结束。java程序内存不够,程序就结束了,OOM

内存泄漏:指程序在运行过程中,申请的内存空间无法被回收或释放,导致系统中的可用内存逐渐减少,最终耗尽可用内存。

2.可达性分析算法(Java使用的这一种)

Java中定义了一些起始点,称为GC Root(正在使用的对象或量),当有对象引用它的时候,就把对象挂载在它下面,形成一个树状结构,当一个对象处于一个这样的树里时,就认为此对象是可达的,反之是不可达

GC ROOT 四种对象:

  1. 虚拟机栈中引用的对象
  2. 方法区类的静态成员引用的对象
  3. 方法区常量引用的对象
  4. 本地方法栈中JNI(Java Native Interface的缩写)引用的对象

垃圾收集算法

1.标记清除(Mark-Sweep)

算法分为“标记”和“清除”两个阶段:首先标记出所有需要回收的对象(引用计数法或者可达性分析),在标记完成后统一回收掉所有被标记的对象。它是最基础的收集算法,后续的收集算法都是基于这种思路并对其缺点进行改进而得到的

它的主要缺点有两个:一个是效率问题,标记和清除过程的效率都不高;另外一个是空间问题,标记清除之后会产生大量不连续的内存碎片,空间碎片太多可能会导致,当程序在以后的运行过程中需要分配较大对象时无法找到足够的连续内存而不得不提前触发另一次垃圾收集动作。


2.标记复制(Copying)

复制算法在标记清除算法的基础上,针对内存碎片问题做了一下优化,此算法把内存分为大小相同的两块,每次在使用的时候只使用其中的一块。当一块内存用完的时候。把存活对象复制到另外的一块中,然后清除当前这块中的所有的对象,如此反复。

缺点:使用当前算法,解决了内存碎片化严重的问题,但是存在缺陷就是每次只使用一半的空间,空间利用率受到影响。同时对于存活周期长的对象,复制次数多

复制收集算法在对象存活率较高时就要执行较多的复制操作,效率将会变低。更关键的是,如果不想浪费50%的空间,就需要有额外的空间进行分配担保,以应对被使用的内存中所有对象都100%存活的极端情况,所以在老年代一般不能直接选用这种算法。


3.标记整理(Mark-Compact)

也叫标记压缩法

根据老年代的特点,有人提出了另外一种“标记-整理”(Mark-Compact)算法,标记过程仍然与“标记-清除”算法一样,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存,缺点是时间稍慢


4.分代收集算法(Generational Collection)

GC分代的基于一个假设:绝大部分对象的生命周期都非常短暂,存活时间短。

“分代收集”(Generational Collection)算法,把Java堆分为新生代和老年代,这样就可以根据各个年代的特点采用最适当的收集算法。

老年代中因为对象存活率高、没有额外空间对它进行分配担保,就必须使用“标记-清理”或“标记-整理”算法来进行回收。

永久代,指方法区,这里不做讨论。

新生代,又分为伊甸园区和幸存区,使用标记复制算法。所有new出来的对象,都先存入伊甸园区,较大的对象伊甸园区可能没有足够的空间,可能会直接放到老年代区。

幸存区又可分为工作区和等待区,当伊甸园区存满垃圾回收(minorGC),会将伊甸园区域和幸存区的工作区A进行标记,将不是垃圾的对象,复制到幸存区的等待区B,之后B区就是工作区,A区变成等待区。

当对象经过多次(15次)新生代垃圾回收,依然存活,这个对象就会存入老年代。

如果老年代满了(触发FullGC,将老年代和新生代一起GC),会进行垃圾回收,使用标记整理(压缩)算法。

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

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

相关文章

【Spring Cloud】Consul

官网介绍: Spring Cloud Consul该项目为Spring Boot应用程序提供了与Consul的集成,通过自动配置和绑定到Spring环境以及其他Spring编程模型习语。通过几个简单的注解,您可以在应用程序内部快速启用和配置常见模式,并使用基于Consul的组件构建大型分布式系统。提供的模式包括…

【网络编程】第十一章 数据链路层 - 以太网(MAC+MTU+ARP+MSS+RARP)

文章目录 重点链路层以太网MAC帧格式碰撞域MAC地址MAC地址和IP地址 MTU-最大传输单元MTU 对 IP 的影响MTU 对 UDP 的影响MTU 对 TCP 的影响-MSS ARP协议ARP协议的工作流程ARP请求的过程ARP应答的过程 ARP 缓存中间人攻击 RARP协议 重点 数据链路层的作用:两个设备 …

如何解决大数据背景下的数据治理挑战

在大数据背景下,数据治理面临着诸多挑战,这些挑战涵盖了数据的复杂性、安全性、合规性、技术选择、文化和组织变革等多个方面。为了有效解决这些挑战,可以从以下几个方面入手: 一、明确数据治理目标和策略 与业务战略紧密结合&a…

虚幻5|AI视力系统,听力系统,预测系统(2)听力系统

虚幻5|AI视力系统,听力系统,预测系统(1)视力系统-CSDN博客 一,把之前的听力系统,折叠成函数,复制粘贴一份改名为听力系统 1.小个体修改如下,把之前的视力系统改成听力系统 2.整体修…

解决Jasper Studio预览无数据源的问题:在Dataset and Query里面预览数据为空,但是浏览器访问接口,是存在数据的。

目录 1.1、错误描述 1.2、解决方案 1.1、错误描述 最近接触Jasper Studio报表开发比较多一些,遇到了很多的问题,其中有一个问题就是:在Jasper Studio中的Dataset and query里面预览数据,发现是空的,如下图所示&…

数据仓库ETL开发

在企业数字化转型的过程中,数据仓库已经成为了企业管理和决策的重要工具。数据仓库ETL开发是构建数据仓库的关键步骤之一,它可以帮助企业从源系统中抽取、清洗、转换和整合数据,方便企业进行管理和分析。本文将介绍如何高效实现数据仓库ETL开…

媒体服务zlmediakit系统架构图

1. 整体系统架构图 (Overall System Architecture Diagram) 描述: 整体系统架构图展示了ZLMediaKit的主要组件及其交互方式,包含流媒体接入、处理、存储和分发等主要流程。 样例图: ------------------------------------------ | 客户端 (Clients…

【功能自动化】WebTours:使用unittest编写注册测试用例

环境搭建: 需要配置WebTours网站 代码实现: # 导入包 from selenium import webdriver from selenium.webdriver.support.select import Select from time import sleep import unittestdriver None class Reg(unittest.TestCase):classmethoddef se…

Spring底层机制环境搭建

文章目录 1.模块创建和依赖引入1.聚合模块,下面有一个myspring2.查看父模块是否管理了子模块3.myspring模块引入基本包 2.进行环境搭建1.目录概览2.UserController.java3.UserService.java4.UserDao.java5.AppMain.java6.beans.xml7.测试8.配置UserController.java为…

掌握电子邮件的艺术:使用 Mailbird 统一管理您的数字生活

在数字时代,电子邮件已成为我们沟通的骨干。无论是商务交流、家庭联络,还是订阅更新,我们几乎每天都在使用电子邮件。但随着账户数量的增加,管理这些账户变得日益复杂。如何有效地整合和优化您的电子邮件体验?Mailbird…

SQL——建表时是否需要设置外键?从哪些方面考虑?

1. 设置外键&不设置外键区别和影响 在数据库设计中,是否设置外键会对数据的完整性、安全性、性能等多个方面产生影响。以下是设置外键与不设置外键的区别和影响: 1. 数据完整性 设置外键: 强制数据完整性: 外键约束确保引用关系中的数据保持一致性…

Ubuntu上安装任意版本Nodejs

Ubuntu系统上安装Node.js可以通过多种方法来实现,包括利用Ubuntu仓库、NodeSource仓库,或者通过nvm(Node Version Manager)来进行。此处将重点介绍如何通过nvm这一流行方法来安装任意版本的Node.js,因为这种方式提供了…

【PaperInFive-时间序列预测】TSMixer:用于时间序列预测的全MLP架构(谷歌)

全文总结:本文研究了线性模型用于时间序列预测的能力,提出了时间序列混合器(TSMixer),一种通过堆叠多层感知器(mlp)设计的新架构。TSMixer在时间和特征维度上交替应用mlp,在概念上对应于时间混合和特征混合操作,有效地…

AI开发者大赛 | 6道算法赛题上新

2024 AI开发者大赛正在如火如荼地进行着,本届比赛吸引了全球范围内的众多优秀开发者参与其中,用代码书写未来,用算法改变世界。 如今,算法赛新一批赛题上线,无论是初学者还是资深开发者,你都可以在2024 AI…

ClickHouse集群的安装

目录 1.clickhouse中文文档地址 2.centos安装部署 2.1采用tgz的方式安装 2.2修改配置文件 2.3修改数据目录 2.4创建角色和目录 3 集群安装 3.1配置文件修改 3.2启动zookeeper 3.3启动clickhouse-server 3.4任意节点连接clickhouse 3.5查看集群 3.6建库 3.7查看数…

【Kotlin】在Kotlin项目中使用AspectJ

前言 AOP编程在Java开发中是一个非常火热的话题,最著名的库为AspectJ Kotlin项目中,通过Gradle插件,也能够使用该库,这是我们下面讲解的重点 由于AspectJ的原理是在预编译阶段,通过插件修改代码,生成代理…

了解住宅代理和移动代理的工作原理:从基础到高级应用

在当今时代,代理技术已经成为了优化网络连接、提升数据安全和增强用户体验的重要工具。特别是住宅代理和移动代理,这两种代理类型在网络服务中扮演着越来越重要的角色。本文将从详细的为您介绍这两种代理服务的工作原理,帮助你更好地理解并应…

如何对 GitLab 中文版进行升级?

极狐GitLab 是 GitLab 在中国的发行版,专门面向中国程序员和企业提供企业级一体化 DevOps 平台,用来帮助用户实现需求管理、源代码托管、CI/CD、安全合规,而且所有的操作都是在一个平台上进行,省事省心省钱。可以一键安装极狐GitL…

ArcGIS空间自相关 (Global Moran‘s I)——探究人口空间格局的20年变迁

先了解什么是莫兰指数? 莫兰指数(Morans I)是一种用于衡量空间自相关性的统计量,即它可以帮助我们了解一个地理区域内的观测值是否彼此相关以及这种相关性的强度和方向。 白话版:一句话就是判断数据在空间上有没有自…

Prometheus 和 Grafana 通过nginx-exporter监控nginx

在生产环境下,您已经部署了 Prometheus 和 Grafana,并希望通过它们来监控另一台 Ubuntu 20.04 上的 Nginx 服务。以下是配置步骤: 1. 安装和配置 nginx-exporter (Nginx 的 Prometheus 导出器) nginx-exporter 是 Prometheus 用来从 Nginx …