20230314整理

1.JVM内存区域

在这里插入图片描述
程序计数器:字节码解释器通过改变程序计数器来依次读取指令,在多线程的情况下,程序计数器用于记录当前线程执行的位置,从而当线程被切换回来的时候能够知道该线程上次运行到哪儿了。它的生命周期随着线程的创建而创建,随着线程的结束而死亡。
Java虚拟机栈:Java 方法调用都是通过栈来实现,每一次方法调用都会有一个对应的栈帧被压入栈中,每一个方法调用结束后,都会有一个栈帧被弹出。每个栈桢包含局部变量表、操作数栈、动态链接、方法返回地址。
本地方法栈:和虚拟机栈所发挥的作用非常相似,区别是: 虚拟机栈为虚拟机执行 Java 方法 (也就是字节码)服务,而本地方法栈则为虚拟机使用到的 Native 方法服务。
:此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例以及数组都在这里分配内存,堆内存结构如下图:
在这里插入图片描述

方法区:方法区会存储已被虚拟机加载的 类信息、字段信息、方法信息、常量、静态变量、即时编译器编译后的代码缓存等数据。Classloader加载类就是存在这个地方。

总的来说,栈负责执行,堆负责存储

2.对象的创建

Step1:类加载检查,虚拟机遇到一条 new 指令时,首先将去检查这个指令的参数是否能在常量池中定位到这个类的符号引用,并且检查这个符号引用代表的类是否已被加载过、解析和初始化过。如果没有,那必须先执行相应的类加载过程。

Step2:分配内存,在类加载检查通过后,接下来虚拟机将为新生对象分配内存。

Step3:初始化零值,内存分配完成后,虚拟机需要将分配到的内存空间都初始化为零值(不包括对象头),这一步操作保证了对象的实例字段在 Java 代码中可以不赋初始值就直接使用,程序能访问到这些字段的数据类型所对应的零值

Step4:设置对象头
初始化零值完成之后,虚拟机要对对象进行必要的设置,例如这个对象是哪个类的实例、如何才能找到类的元数据信息、对象的哈希码、对象的 GC 分代年龄等信息。 这些信息存放在对象头中

Step5:执行 init 方法,执行 new 指令之后会接着执行 方法

3.类加载器

3.1类加载流程:
从类被加载到虚拟机内存中开始,到释放内存总共有 7 个步骤:加载,验证,准备,解析,初始化,使用,卸载。其中验证,准备,解析三个部分统称为连接

(1)加载:将 class 文件加载到内存将静态数据结构转化成方法区中运行时的数据结构在堆中生成一个代表这个类的 java.lang.Class 对象作为数据访问的入口

(2)链接验证:确保加载的类符合 JVM 规范和安全,保证被校验类的方法在运行时不会做出危害虚拟机的事件,其实就是一个安全检查准备:为 static 变量在方法区中分配内存空间,设置变量的初始值,例如 static int a = 3 (注意:准备阶段只设置类中的静态变量(方法区中),不包括实例变量(堆内存中),实例变量是对象初始化时赋值的)解析:虚拟机将常量池内的符号引用替换为直接引用的过程(符号引用比如我现在 import java.util.ArrayList 这就算符号引用,直接引用就是指针或者对象地址,注意引用对象一定是在内存进行)

(3)初始化:其实就是执行类构造器方法的()的过程,而且要保证执行前父类的()方法执行完毕。这个方法由编译器收集,顺序执行所有类变量(static 修饰的成员变量)显式初始化和静态代码块中语句。此时准备阶段时的那个 static int a 由默认初始化的 0 变成了显式初始化的 3。 由于执行顺序缘故,初始化阶段类变量如果在静态代码块中又进行了更改,会覆盖类变量的显式初始化,最终值会为静态代码块中的赋值。
(4)卸载:GC 将无用对象从内存中卸载

3.2类加载器的加载顺序:
加载一个 Class 类的顺序也是有优先级的,类加载器从最底层开始往上的顺序是这样的
BootStrap ClassLoader:rt.jar
Extension ClassLoader: 加载扩展的 jar 包
App ClassLoader:指定的 classpath 下面的 jar 包
Custom ClassLoader:自定义的类加载器

3.3双亲委派机制
当一个类收到了加载请求时,它是不会先自己去尝试加载的,而是委派给父类去完成,比如我现在要 new 一个 Person,这个 Person 是我们自定义的类,如果我们要加载它,就会先委派 App ClassLoader ,只有当父类加载器都反馈自己无法完成这个请求(也就是父类加载器都没有找到加载所需的 Class)时,子类加载器才会自行尝试加载。这样做的好处是,加载位于 rt.jar 包中的类时不管是哪个加载器加载,最终都会委托到 BootStrap ClassLoader 进行加载,这样保证了使用不同的类加载器得到的都是同一个结果。其实这个也是一个隔离的作用,避免了我们的代码影响了 JDK 的代码

4.对象的访问定位

建立对象就是为了使用对象,我们的 Java 程序通过栈上的 reference 数据来操作堆上的具体对象。对象的访问方式由虚拟机实现而定,目前主流的访问方式有:使用句柄、直接指针。

如果使用句柄的话,那么 Java 堆中将会划分出一块内存来作为句柄池,reference 中存储的就是对象的句柄地址,而句柄中包含了对象实例数据与对象类型数据各自的具体地址信息。
在这里插入图片描述

如果使用直接指针访问,reference 中存储的直接就是对象的地址。

在这里插入图片描述

5.GC回收机制

5.1 堆内存介绍
在这里插入图片描述
当我们 new 一个对象后,会先放到 Eden 划分出来的一块作为存储空间的内存,但是我们知道对堆内存是线程共享的,所以有可能会出现两个对象共用一个内存的情况。

当 Eden 区内存空间满了的时候,就会触发 Minor GC,Survivor0 区满不会触发 Minor GC 。那 Survivor0 区 的对象什么时候垃圾回收呢?假设 Survivor0 区现在是满的,此时又触发了 Minor GC ,发现 Survivor0 区依旧是满的,存不下,此时会将 S0 区与 Eden 区的对象一起进行可达性分析,找出活跃的对象,将它复制到 S1 区并且将 S0 区域和 Eden 区的对象给清空,这样那些不可达的对象进行清除,并且将 S0 区 和 S1 区交换。

老年代是存储长期存活的对象的,占满时就会触发我们最常听说的 Full GC,期间会停止所有线程等待 GC 的完成。所以对于响应要求高的应用应该尽量去减少发生 Full GC 从而避免响应超时的问题。而且当老年区执行了 full gc 之后仍然无法进行对象保存的操作,就会产生 OOM,这时候就是虚拟机中的堆内存不足,原因可能会是堆内存设置的大小过小。
在这里插入图片描述

5.2 如何判断一个对象需要被干掉
在这里插入图片描述
图中程序计数器、虚拟机栈、本地方法栈,3 个区域随着线程的生存而生存的。内存分配和回收都是确定的。随着线程的结束内存自然就被回收了,因此不需要考虑垃圾回收的问题。而 Java 堆和方法区则不一样,各线程共享,内存的分配和回收都是动态的。因此垃圾收集器所关注的都是堆和方法这部分内存。

在进行回收前就要判断哪些对象还存活,哪些已经死去。下面介绍两个基础的计算方法:

1.引用计数器计算:给对象添加一个引用计数器,每次引用这个对象时计数器加一,引用失效时减一,计数器等于 0 时就是不会再次使用的。不过这个方法有一种情况就是出现对象的循环引用时 GC 没法回收。
2.可达性分析计算:这是一种类似于二叉树的实现,将一系列的 GC ROOTS 作为起始的存活对象集,从这个节点往下搜索,搜索所走过的路径成为引用链,把能被该集合引用到的对象加入到集合中。搜索当一个对象到 GC Roots 没有使用任何引用链时,则说明该对象是不可用的。主流的商用程序语言,例如 Java,C#等都是靠这招去判定对象是否存活的。

5.3 如何宣告一个对象的真正死亡
判断一个对象的死亡至少需要两次标记
1.如果对象进行可达性分析之后没发现与 GC Roots 相连的引用链,那它将会第一次标记并且进行一次筛选。判断的条件是决定这个对象是否有必要执行 finalize()方法。如果对象有必要执行 finalize()方法,则被放入 F-Queue 队列中。
2.GC 对 F-Queue 队列中的对象进行二次标记。如果对象在 finalize()方法中重新与引用链上的任何一个对象建立了关联,那么二次标记时则会将它移出“即将回收”集合。如果此时对象还没成功逃脱,那么只能被回收了。

6.垃圾回收算法

标记清除算法: 标记出所有需要回收的对象,标记结束后统一回收。标记和清除的效率比较低下。且这种做法会让内存中的碎片非常多。这个导致了如果我们需要使用到较大的内存块时,无法分配到足够的连续内存
在这里插入图片描述

标记复制算法: 为了解决效率问题,复制算法就出现了。它将可用内存按容量划分成两等分,每次只使用其中的一块,这个算法的代价就是把内存缩水了,这样堆内存的使用效率就会变得十分低下了
在这里插入图片描述

标记整理算法: 复制算法在对象存活率高的时候会有一定的效率问题,标记过程仍然与“标记-清除”算法一样,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,然后直接清理掉边界以外的内存.
在这里插入图片描述

分代收集算法: 这种算法并没有什么新的思想,只是根据对象存活周期的不同将内存划分为几块。一般是把 Java 堆分为新生代和老年代,这样就可以根据各个年代的特点采用最适当的收集算法。在新生代中,每次垃圾收集时都发现有大批对象死去,只有少量存活,那就选用复制算法,只需要付出少量存活对象的复制成本就可以完成收集。而老年代中因为对象存活率高、没有额外空间对它进行分配担保,就必须使用“标记-清除”或者“标记-整理”算法来进行回收。Java1.8默认收集器,就是新生代采用标记-复制算法,老年代采用标记-整理算法。

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

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

相关文章

基于Java+SpringBoot+vue的学生成绩管理系统设计和实现【源码+论文+演示视频+包运行成功】

博主介绍:专注于Java技术领域和毕业项目实战 🍅文末获取源码联系🍅 👇🏻 精彩专栏推荐订阅👇🏻 不然下次找不到哟 Java项目精品实战案例(200套) 目录 一、效果演示 二、…

扯什么 try-catch 性能问题?

“yes&#xff0c;你看着这鬼代码&#xff0c;竟然在 for 循环里面搞了个 try-catch&#xff0c;不知道try-catch有性能损耗吗&#xff1f;”老陈煞有其事地指着屏幕里的代码&#xff1a; for (int i 0; i < 5000; i) {try {dosth} catch (Exception e) {e.printStackTrace…

如何测试一个AI系统?

最近AI大火&#xff0c;chatgpt、GPT-4、文心一言不断的在轰炸着我们的生活、工作&#xff0c;很多时候我们都在感叹这智能化来的太快了。对于一个测试工程师&#xff0c;如何开始测试一个AI系统呢&#xff0c;今天我们就一起来聊聊相关的内容。 智能系统对测试工程师提出的新问…

2023年网络安全比赛--网络安全事件响应中职组(超详细)

一、竞赛时间 180分钟 共计3小时 二、竞赛阶段 1.找出黑客植入到系统中的二进制木马程序,并将木马程序的名称作为Flag值(若存在多个提交时使用英文逗号隔开,例如bin,sbin,…)提交; 2.找出被黑客修改的系统默认指令,并将被修改的指令里最后一个单词作为Flag值提交; 3.找出…

React 用一个简单案例体验一遍 React-dom React-router React-redux 全家桶

一、准备工作 本文略长&#xff0c;建议耐心读完&#xff0c;每一节的内容与上一节的内容存在关联&#xff0c;最好跟着案例过一遍&#xff0c;加深记忆。 1.1 创建项目 第一步&#xff0c;执行下面的命令来创建一个 React 项目。 npx create-react-app react-example cd rea…

Springboot集成Swagger

一、Swagger简介注意点&#xff01; 在正式发布的时候要关闭swagger&#xff08;出于安全考虑&#xff0c;而且节省内存空间&#xff09;之前开发的时候&#xff0c;前端只用管理静态页面&#xff0c; http请求到后端&#xff0c; 模板引擎JSP&#xff0c;故后端是主力如今是前…

【宝塔面板部署nodeJs项目】网易云nodeJs部署在云服务器上,保姆级教程,写网易云接口用自己的接口不受制于人

看了很多部署的&#xff0c;要么少步骤&#xff0c;要么就是写的太简洁&#xff0c;对新手不友好 文章目录前言一、下载网易云nodejs项目1. git clone下载&#xff0c;两种方式2. 运行项目二、使用步骤1. 先在本地运行2.测试接口三、部署服务器1. 在宝塔面板安装pm2管理器2. 压…

字符函数和字符串函数【上篇】

文章目录&#x1f396;️1.函数介绍&#x1f4ec;1.1. strlen&#x1f4ec;1.2. strcpy&#x1f4ec;1.3. strcat&#x1f4ec;1.4. strcmp&#x1f4ec;1.5. strncpy&#x1f4ec;1.6. strncat&#x1f4ec;1.7. strncmp&#x1f396;️1.函数介绍 &#x1f4ec;1.1. strlen …

入行 5年,跳槽 3次,我终于摸透了软件测试这行(来自过来人的忠告)

目录 前言 第一年 第二年 第三年 第四年 作为过来人的一些忠告 前言 最近几年行业在如火如荼的发展壮大&#xff0c;以及其他传统公司都需要大批量的软件测试人员&#xff0c;但是20年的疫情导致大规模裁员&#xff0c;让人觉得行业寒冬已来&#xff0c;软件测试人员的职…

【YOLOv8/YOLOv7/YOLOv5/YOLOv4/Faster-rcnn系列算法改进NO.60】损失函数改进为wiou

前言作为当前先进的深度学习目标检测算法YOLOv8&#xff0c;已经集合了大量的trick&#xff0c;但是还是有提高和改进的空间&#xff0c;针对具体应用场景下的检测难点&#xff0c;可以不同的改进方法。此后的系列文章&#xff0c;将重点对YOLOv8的如何改进进行详细的介绍&…

css属性学习

css属性 就是我们选择器里面 { } 中的内容 字体样式 font-size 控制字体大小&#xff1a;单位px&#xff08;像素&#xff09; 默认字体占16个像素 <p style"font-size:30px;">font-size&#xff1a;字体大小&#xff0c;单位的话可以用px表示占的像素个数&…

Mini-Xml 经典实例Demo

欢迎小伙伴的点评✨✨&#xff0c;相互学习、博主将自己研发xml微型服务器的经验与之分享&#x1f30f;&#x1f30f;&#x1f642; 文章目录前言一、使用mxml库编写Xml文件1.1 经典实例Demo_11.2、经典实例Demo_21.3、经典实例Demo_3二、总结前言 本章将会给大家带来mini-xml…

在我的MacBook上捣鼓ESP8266

周三是我们的篮球日&#xff0c;打篮球后总是会有些兴奋&#xff0c;然后就容易睡不着&#xff0c;额&#xff0c;睡不着就拿我的ESP8266开发板出来捣鼓一下。先下载编译工具链https://github.com/espressif/ESP8266_RTOS_SDK下载sdkgit clone https://github.com/espressif/ES…

C++程序在内存中的模型

进程&#xff08;Process&#xff09;是计算机中的程序&#xff0c;数据集合在其上运行的一次活动&#xff0c;是系统进行资源分配的基本单位。每个进程都有自己独立的虚拟内存地址空间&#xff0c;这个虚拟的内存地址空间一般是线性连续的&#xff0c;这个内存地址空间是虚拟的…

面试官想看我写一篇关于“原型链”和“构造函数”深入理解的文章

前言&#xff1a; 在参加工作的面试过程中&#xff0c;我搬出了我的个人掘金账号写在了简历里&#xff0c;面试官很感兴趣&#xff0c;他不仅关注了我的账号&#xff0c;还想让我写一篇《原型链》的见解&#xff0c;由于老早就想总结一篇关于原型的文章&#xff0c;奈何自己刚开…

07平衡负载:gRPC是如何进行负载均衡的?

负载均衡(Load Balance),其含义就是指将请求负载进行平衡、分摊到多个负载单元上进行运行,从而协同完成工作任务。 负载均衡的主要作用: 提升并发性能:负载均衡通过算法尽可能均匀的分配集群中各节点的工作量,以此提高集群的整体的吞吐量。 提供可伸缩性:可添加或减少服…

Springboot新手开发 Cloud篇

前言&#xff1a; &#x1f44f;作者简介&#xff1a;我是笑霸final&#xff0c;一名热爱技术的在校学生。 &#x1f4dd;个人主页&#xff1a;个人主页1 || 笑霸final的主页2 &#x1f4d5;系列专栏&#xff1a;后端专栏 &#x1f4e7;如果文章知识点有错误的地方&#xff0c;…

汇编语言与微机原理(1)基础知识

前言&#xff08;1&#xff09;本人使用的是王爽老师的汇编语言第四版和学校发的微机原理教材配合学习。&#xff08;2&#xff09;推荐视频教程通俗易懂的汇编语言&#xff08;王爽老师的书&#xff09;&#xff1b;贺老师C站账号网址&#xff1b;&#xff08;3&#xff09;文…

在visual studio 2022 C++中配置最新版OpenCV和可能错误解决方案

前面我们写了一篇博文有关在C#中配置OpenCV&#xff0c;但C#版本的OpenCV的学习资源相对较少&#xff0c;C版的和Python版的比较多。这里先说说C版的如何配置吧&#xff01;总共完成四步即可使用起来。 文章目录一、下载并安装OpenCV1、下载OpenCV2、安装OpenCV二、配置环境1、…

【python】喜欢XJJ?这不得来一波大采集?

前言 大家早好、午好、晚好吖 ❤ ~欢迎光临本文章 俗话说的好&#xff1a;技能学了~就要用在自己喜欢得东西上&#xff01;&#xff01; 这我不得听个话~我喜欢小姐姐&#xff0c;跳舞的小姐姐 这不得用python把小姐姐舞采集下来~嘿嘿嘿 完整源码、素材皆可点击文章下方名片…