【JVM】(内存区域划分 为什么要划分 具体如何分 类加载机制 类加载基本流程 双亲委派模型 类加载器 垃圾回收机制(GC))

news2024/10/6 10:23:18

文章目录

  • 内存区域划分
    • 为什么要划分
    • 具体如何分
  • 类加载机制
    • 类加载基本流程
    • 双亲委派模型
      • 类加载器
  • 垃圾回收机制(GC)


内存区域划分

为什么要划分

JVM启动的时候会申请到一整个很大的内存区域,JVM是一个应用程序,要从操作系统这里申请内存,JVM就需要根据,把空间,分成几个部分,每个部分各自有不同的功能作用.

具体如何分

在这里插入图片描述

存放new出来的对象
方法区/元数据区,存放类对象(类加载之后,存放的位置)
存放方法之间的调用关系
程序计数器 存放每个线程,下一条要执行的指令的地址

在这里插入图片描述

类加载机制

类加载基本流程

java代码会被编译成.class文件(包含一些字节码),java程序要想运行起来,就需要让jvm读取到这些.class文件,并且把里面的内容,构造成类对象,保存到内存的方法区中。所谓的执行代码就是调用方法。
书上和官方文档把类加载过程分成了5个步骤。

  1. 加载:找到.class文件,打开文件,读取到文件内容。
  2. 验证:.class文件是一个二进制的格式。(某个字节,都是具有特定含义的),就需要验证你当前读到的这个格式是否符合要求。
  3. 准备:给类对象分配内存空间。(只分配内存空间,没有初始化,此时空间上的内存的数值是0,此时如果尝试打印类的static成员,就是全0的)
  4. 解析:针对类对象中包含的字符串常量进行处理,进行一些初始化操作。(java代码中用到的字符串常量在编译之后也会进入到.class文件中)这个过程也叫做:把“符号引用”(文件偏移量)替换成“直接引用”(内存地址)。
  5. 初始化:针对类对象进行初始化,把类对象中需要的各个属性都设置好,还需要初始化好static成员,还需要执行静态代码块,还可能需要加载一下父类。

双亲委派模型

属于类加载中,第一个步骤“加载”过程中国,其中的一个环节。
负责根据全限定类名找到.class文件。

所谓的“双亲委派模型”就是一个查找优先级问题。

类加载器

是JVM中的一个模块,在JVM中内置了三个类加载器。

  1. BootStrap ClassLoader
  2. Extension ClassLoader
  3. Application ClassLoader

上述三个类加载有父子关系,3是子 2是父 3是爷。
在这里插入图片描述

双亲委派模型过程:

类加载的过程(找class文件的过程)

  • 给定一个类的全限定类名,形如java.lang.String。
  • 从Application ClassLoader作为入口,开始执行查找的逻辑。
  • Application ClassLoader,不会立即去扫描自己负责的目录(负责的是搜索项目点前目录和第三方库对应的目录)而是把查找的任务,交给他的父亲,Extension ClassLoader。
  • Extension ClassLoader 也不会立即去扫描自己负责的目录,(负责的是JDK中一些扩展的库,对应的目录)而是把查找的任务,交给他的父亲,BootStrap ClassLoader。
  • BootStrap ClassLoader 也不想立即扫描自己负责的目录,(负责的是标准库的目录),也想把任务交给它的父亲,结果发现自己没有父亲,因此BootStrap ClassLoader只能亲自负责扫描,标准库的目录。java.lang.String这种类就能够在标准库中,找到对应的.class文件,就可以进行打开文件,读取文件后续操作。此时查找.class文件的过程就结束了。但是,如果给定的类不是标准库的类,任务仍然会被交给孩子来执行。
  • 如果没有扫描到就会回到Extension ClassLoader。Extension ClassLoader就会扫描负责的扩展库的目录,如果找到,就执行后续的类加载操作,此时查找过程结束,如果没找到,还是把任务交给孩子来执行。
  • 没有扫描到,就会回到Application ClassLoader,Application ClassLoader就会负责扫描当前目录和第三方库的目录,如果找到,就会执行后续的类加载操作,如果没找到,就会抛出一个ClassNotFoundExcepton。

之所以搞这一套流程,主要目的是为了确保,标准库的类,被加载的优先级最高,其次是扩展库,最后是自己写的类和第三方库

在这里插入图片描述

在这里插入图片描述

垃圾回收机制(GC)

让JVM自行判定,某个内存是否就不再使用了,如果这个内存后面确实不用了,JVM就会自动的把这个内存给回收掉,此时就不必要让程序员自己手动写代码回收。

GC这么好为什么C++不引入GC呢?

  1. 系统缺陷,需要一个/一些特定的线程,不停的扫描内存中的所有的对象,看是否能够回收。此时是需要额外的内存 + CPU资源的。C++要考虑能兼容一些配置特别低的系统。
  2. 效率问题,这样的扫描线程,不一定能够及时的释放内存(扫描总是有一定周期的),一旦同一时刻,出现大量的对象都需要被回收GC产生的负担就会很大,甚至引起整个程序都卡顿。(STW问题 stop the world)。
    GC是垃圾回收,GC回收的目标是内存中的对象,对于Java来说就是new出来的对象。栈里的局部变量,是跟随栈帧的生命周期走的。(方法执行结束,栈帧销毁,内存自然释放)
    静态变量,生命周期就是整个程序,这个始终存在,就意味着静态变量是无需释放的。

GC可以理解成两个大的步骤:

  • 找到垃圾
  1. 引用计数(Python PHP)
    new出来的对象,单独安排一块空间,来保存一个计数器。
    在这里插入图片描述
    缺陷:
    1.浪费内存
    在这里插入图片描述
    2.引用计数机制,存在“循环引用”问题。

在这里插入图片描述
此时第一个对象和第二对象互相引用,要想使用第一个对象,就需要先拿到第二个对象,如果想要拿到第二个对象,又得先拿到第一个对象,这里就非常像死锁。

  1. 可达性分析(Java)

本质上就是时间换空间这样的手段,有一个/一组线程,周期性的扫描我们代码中所有的对象。(从一些特定的对象触发,尽可能的进行访问的遍历,把所有能够访问到的对象都标记成“可达”,反之经过扫描之后,未被标记的对象就是垃圾(“不可达”)了)
可达性分析出发点很多,不仅仅是所有的局部变量,还有常量池中引用的对象,还有方法区中的静态引用的变量。 这些统称为GCRoots。
可达性分析都是周期性进行的,当前某个对象是否是垃圾,是随着代码的执行,会发生改变。(可达性分析比较消耗系统资源,开销比较大)

  • 回收垃圾

三种基本思路

  1. 标记清除

把对应的对象,直接释放掉,就是标记清楚的方案,这个方案会产生很多的内存碎片,释放内存是为了让别的代码能够申请,申请内存,都是申请到“连续”的内存空间。

优点:实现简单。

缺点:产生不连续的内存碎片,如果程序需要分配一个连续内存的大对象时,就需要提前触发一次垃圾回收。

在这里插入图片描述

  1. 复制算法

通过复制的方式把有效的对象,归类到一起,再统一释放剩下的空间。

在这里插入图片描述
优点:执行效率高,没有内存碎片的问题。

缺点:空间利用率低,因为复制算法每次只能使用一半的内存。

  1. 标记整理

既能够解决内存碎片化的问题,又能够处理复制算法中利用率低的问题。

类似于顺序表删除元素的搬运操作。搬运的开销仍然很大。
在这里插入图片描述
优点:解决了内存碎片问题,比复制算法空间利用率高。

缺点:因为有局部对象移动,所以效率不是很高。

实际上JVM采取的释放思路,是上述基础思路结结合体,让上述方案扬长避短。

分代回收:

在这里插入图片描述

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

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

相关文章

jscpd对项目进行查重(支持150+类语言)

jscpd jscpd 查重时能够跳过标记为忽略的块和新行以及空符号和注释&#xff08;不支持尖括号注释<!-- --&#xff01;>&#xff09;&#xff0c;重复率判定依据为一定长度标识符的MD5值是否相同。 安装 npm install -g jscpd配置参数(查看更多) OptionTypeDefaultDes…

【C语言基础】:字符函数和字符串函数

文章目录 一、字符函数1. 字符分类函数2. 字符转化函数 二、字符串函数1. strlen函数的使用和模拟实现strlen函数的使用strlen函数的模拟实现 2. strcpy函数的使用和模拟实现strcpy函数的使用strcpy函数的模拟实现 3. strcat函数的使用和模拟实现strcat函数的使用strcat函数的模…

5 个最佳 Mock 工具

在持续发展的前端开发领域&#xff0c;一套高效的自动化工具是关键。这篇文章将带你了解五个出色的模拟工具&#xff0c;它们能极大提升你的生产力、简化数据仿真&#xff0c;并提升接口测试效率。对于寻求提高工作流的前端开发者来说&#xff0c;它们是必不可少的。让我们开始…

牛客题霸-SQL入门篇(刷题记录二)

本文基于前段时间学习总结的 MySQL 相关的查询语法&#xff0c;在牛客网找了相应的 MySQL 题目进行练习&#xff0c;以便加强对于 MySQL 查询语法的理解和应用。 以下内容是牛客题霸-SQL入门篇剩余的第 21-39 道题目的 SQL 代码答案。 由于涉及到的数据库表较多&#xff0c;因…

Jira自动化的实用工具——ScriptRunner简介及最佳实践

近日&#xff0c;龙智举办的DevSecOps研讨会年终专场“趋势展望与实战探讨&#xff1a;如何打好DevOps基础、赋能创新”在上海圆满落幕。龙智Atlassian技术与顾问咨询团队&#xff0c;以及清晖、JamaSoftware、CloudBees等生态伙伴的嘉宾发表了主题演讲&#xff0c;分享他们在D…

【鸿蒙HarmonyOS开发笔记】常用组件介绍篇 —— Progress进度条组件

概述 Progress为进度条组件&#xff0c;用于显示各种进度。 参数 Progress组件的参数定义如下 Progress(options: {value: number, total?: number, type?: ProgressType})● value value属性用于设置当前进度值。 ● total total属性用于设置总值。 ● type type属…

小程序搜索排名优化二三事

小程序的优化主要是排名优化和性能优化两个版块。性能优化这方面主要靠开发者自己完善&#xff0c;我们团队提供的服务就是把产品的排名打上去&#xff0c;获得更多的自然流量&#xff0c;实现盈利。 如何提升小程序的搜索排名主要从如下几个方面出发&#xff1a; 首先要知道…

nodeJs 学习

常用快捷键 二、fs模块 回调函数为空&#xff0c;则表示写入成功&#xff01; 练习 const fs require(fs); fs.readFile(../files/成绩.txt, utf-8, (err, dataStr) > {if (err) {console.log(读取失败);return err;}console.log(读取成功);const arr dataStr.split( )co…

B007-springcloud alibaba 消息驱动 Rocketmq

目录 MQ简介什么是MQMQ的应用场景异步解耦流量削峰 常见的MQ产品 RocketMQ入门RocketMQ环境搭建环境准备安装RocketMQ启动RocketMQ测试RocketMQ关闭RocketMQ RocketMQ的架构及概念RocketMQ控制台安装 消息发送和接收演示发送消息接收消息 案例订单微服务发送消息用户微服务订阅…

华中师范大学伍伦贡联合研究院与南京大学联合主办——第三届人工智能、物联网和云计算技术国际会议(AIoTC 2024)

#先投稿&#xff0c;先送审# 第三届人工智能、物联网和云计算技术国际会议&#xff08;AIoTC 2024&#xff09; 2024 3rd International Conference on Artificial Intelligence, Internet of Things and Cloud Computing Technology 2024年8月2-4日 | 中国南京 重要信息 大…

1.详细解释单链表中的头结点;2.Java算法——力扣707题:设计链表

1.详细解释单链表中的头结点 在做这道算法之前&#xff0c;首先务必要弄明白三个问题&#xff1a; 对于含头节点的单链表&#xff0c; 头结点是否是第一个节点&#xff1f;单链表的长度是否包含该头节点&#xff1f;头结点是否有索引&#xff1f;如果有的话&#xff0c;又是多…

[保姆级教程]Windows安装MongoDB教程

文章目录 MongoDB安装包下载1.点击进入mongodb官网2.点击MongoDB Community Edition&#xff08;社区版&#xff09;&#xff0c;进入下图界面3.选择版本4.下载5.安装6.勾选同意协议&#xff0c;点击“Next"7.选择自定义安装8.点击“Next"9.修改到合适的地址10.点击i…

linux 使用docker安装 postgres 教程,踩坑实践

linux 使用docker安装 postgres 教程 踩坑实践,安装好了不能远程访问。 防火墙已关闭、postgres 配置了允许所有ip 访问、网络是通的。端口也是开放的&#xff0c;就是不能用数据库链接工具访问。 最后发现是云服务器端口没开 ,将其打开 到这一步完全正确了&#xff0c;但是…

Springboot笔记-01

简化spring应用开发&#xff0c;约定大于配置 简化Spring应用开发的一个框架&#xff1b; 整个Spring技术栈的一个大整合&#xff1b; J2EE开发的一站式解决方案&#xff1b; 优点&#xff1a; 快速创建独立运行的spring项目以及于主流框架集成 使用嵌入式的Servlet容器&#x…

HarmonyOS NEXT应用开发—多层级轮播图案例

介绍 本示例介绍使用ArkUIstack 组件实现多层级瀑布流。该场景多用于购物、资讯类应用。 效果图预览 使用说明 加载完成后显示轮播图可以左右滑动。 实现思路 SwiperDataSource&#xff0c;实现IDataSource接口的对象&#xff0c;用于LazyForEach加载数据。源码参考Swiper…

iframe重新加载最简单的方法!初次渲染和更新后渲染不会引起其他页面变动

我们项目有一个【加载场景】【切换场景】的需求&#xff0c;iframe是子组件&#xff0c;数据传过去之后没有重新加载 &#xff0c;我测试发现 重新渲染的时候&#xff0c;iframe的load方法没有重新加载&#xff0c;数据变动后也不会影响&#xff0c;然后我用了网上好几种方法&a…

一个简单的Vue2例子讲明白拖拽drag、移入dragover、放下drop的触发机制先后顺序

几个小细节说明&#xff1a; 执行顺序dragstart→dragover→drop被拖拽的物体必须要设置draggable"true"&#xff08;实际上只需要draggable就可以了&#xff0c;默认就是true&#xff09;&#xff0c;否者默认一般是不允许被拖拽的&#xff08;图片除外&#xff09;…

将main打包成jar;idea打包main为jar包运行

将main打包成jar&#xff1b;idea打包main为jar包运行 适用场景&#xff1a;可以封装一些小工具。 配置jar Maven中添加 <packaging>jar</packaging>将其打包为jar。 设置运行入口main 编译jar 看到jar输出 运行效果&#xff1a; 其中&#xff0c;三方依赖也被…

CLIP解读

1、引言 在计算机视觉领域&#xff0c;通常需要经过训练模型来实现对预定类别目标预测&#xff08;如分类、检测等任务&#xff09;&#xff0c;但是这种形式会限制模型的通用性。比如我们训练完了一个猫狗分类模型&#xff0c;如果现在希望识别一只老虎&#xff0c;那么原来训…

【Qt】Qt中的常用属性

需要云服务器等云产品来学习Linux可以移步/-->腾讯云<--/官网&#xff0c;轻量型云服务器低至112元/年&#xff0c;新用户首次下单享超低折扣。 目录 一、QWidget属性一览 二、属性enabled(可用状态) 三、属性geometry(修改位置和尺寸) 1、QRect类型的结构 2、geome…