JVM面试必备

目录

JVM三大问题

一、JVM内存区域划分

​编辑

二、JVM类加载机制

双亲委派模型(常考)

类加载的格式,类卸载

三、垃圾回收(GC)

具体垃圾回收GC步骤

1.判定对象是否为垃圾

方案1:引用计数

方案2:可达性分析

2.释放对象的内存

1.标记-清除(直接释放)

2.复制算法

3.标记整理

4.JVM的垃圾回收机制


JVM三大问题

一、JVM内存区域划分

首先来到第一个问题:什么是JVM呢

JVM可以说是java的虚拟机,也可以叫做java的一个进程,每一个java进程都是JVM实例

堆,栈,方法区,程序计数器

成员变量->堆

局部变量,(引用类型也包括)->栈

静态变量->方法区

一个进程的运行过程中,就要从操作系统这里申请一些内存资源,JVM也是如此,搞了一大块内存供java代码执行的时候使用,JVM吧这一块内存,又划分出几个区域,作为不同用途。

二、JVM类加载机制

把类从硬盘文件加载到内存中

JAVA程序,最开始是写.java文件,编译成.class文件(字节码),运行java程序,JVM就会读取.class文件,把文件的内容放到内存中,并且构造成.class对象(类对象)

1.加载

找到.class文件,打开文件,读取文件内容,并且尝试解析格式

在JAVA代码中是直接的使用类

2.验证

验证当前.class文件是否符合要求

介绍一下上面的字段意思:

access_flags(相当于是不是public)

attribute注解

minor_version:小版本号

constant-pool:常量池

java文件里写的信息有什么,.class文件有所体现。

3.准备

给类对象分配内存,最终的目标就是构建出完整的类对象,分配内存+初始化。

4.解析

主要是初始化类对象涉及到一些字符串常量,其实字符串常量在.class文件就有了,直接读到内存中就行了。

常量池内符号引用,替换为直接引用的过程。(相对位置,经过偏移换到真实的内存地址)

相对位置是什么意思:我们去看电影,我知道电影的位置吗,不知道,因为我不知道他那个厅是怎么样的,但是我知道我坐在小美的旁边。

5.初始化

对类对象进行更具体的初始化操作,初始化静态成员,初始化静态代码块,加载父类

双亲委派模型(常考)

描述在类加载过程中,如何寻找.class文件。java圈子喜欢高大上的名字,比如自动装箱拆箱(其实不过也只是一个类型转换),

JVM加载.class文件的时候需要用到类加载器模块,JVM带了三个类加载器

Bootstrap ClassLoader

负责加载标准库的类,JAVA有标准文档,描述了都要提供哪些类,

Extension ClassLoader

负责加载JVM扩展的库,除了标准库之外,实现JVM厂商,还会添加一些类

Application ClassLoader

负责加载第三方库,像之前用到的mysql,jdbc,servlet(自己代码中写的类)

此处父子,不是父类子类,继承,而是对象有一个parent引用,指向父类类加载器实例

1. 从Application ClassLoader开始,但是他并不会立即搜索第三方库的目录,而是把加载任务委派给父亲,让父亲先加载

2.到了Extension ClassLoader,也不会立即搜索扩展库目录,也是把加载任务委派给父亲,也让父亲先尝试加载。

3.到了Bootstrap ClassLoader,也不想理机搜索标准库,而是也想把任务给父亲,但是他没有父亲,只能自己动手来搜索了

如果找到了这个类,会进行后续的加载(也就和Application和Extension没关系了)没找到,则把任务还给孩子,给Extension完成

4.任务再次回到Extension ClassLoader手上,他就要搜索扩展库的目录,看没有匹配的,.class文件找到,走,没找到就给他的孩子

5.任务回到了Application ClassLoader,就要搜索第三方库的目录(往往是你的项目目录,以及和jvm一些配置项有关-classpath有关系    找到了,就进行后续的加载,找不到,就要抛异常)

类加载中,更重要,更关键的是针对.class文件的解析校验。

类加载的格式,类卸载

一个类,什么时候会被加载呢?(懒汉模式 当我用到了才会加载)

1.构造类的实例

2.使用了类的静态方法/静态属性

3.子类的加载会触发父类

类加载后,后续就不必加载了

类卸载(把类对象干掉)

属于是特殊情况

一般来说

一般来说类加载过后就不必考虑卸载。一直保存到程序运行结束

但是有的特殊场景可能用到卸载操作

有的服务器需要打,“热补丁”

代码有bug,正常操作是修改代码,重新编译,用新的版本来去代替旧版本,重启服务器,有些特殊情况,服务器不方便重启,可以通过打补丁的方式,通过一些特殊手段,把需要替换的类给卸载掉,直接用加载好的类去替换(新版代码)

有些情况不方便去重启服务器,就可以通过“打补丁”的方式把需要替换的类替换掉,直接用加载好的类卸载掉,直接用加载好的新的类替换(新版代码)

热“并不需要重启,也不需要重新编译”

冷“不需要重新编译,但是需要重启“

JAVA这里用的补丁较少,游戏可能会多一点,比如不停服更新

三、垃圾回收(GC)

于是JAVA引入了垃圾回收机制,自动去判定,某个内存是否会被继续使用(如果不会就把这个内存当成垃圾)

JVM有好多内存分区,那么GC回收的是哪里的对象呢?

栈首先不需要GC去回收,栈里面包含很多栈帧

栈不需要GC回收吗,栈里包含很多”栈帧“,一个栈帧对应一个方法,该方法执行结束,此时这个栈帧就销毁了,栈帧上的局部变量啥的自然销毁。

程序计数器同理,线程销毁,自然也跟着销毁

方法区,类对象,很少会涉及到对象的卸载

堆才是GC的主要战场

具体垃圾回收GC步骤

1.判定对象是否为垃圾

判定对象是否是垃圾的方式->看是否有引用指向他

方案1:引用计数

给这个对象安排一个计数器,每次有引用指向他它,就把计数器+1,每次引用被销毁,计数器-1,当计数器为0的时候,意味着该对象就是垃圾了。

下列代码是对应的过程。

引用计数的两个明显的缺陷:

1.空间利用率比较低,浪费更多的内存空间

如果给引用计数分配了两个字节,对象本体才四个字节的话,引用计数就浪费了50%的空间,如果代码中都是这些小对象,并且数量众多,此时浪费非常明显了就。

2.可能存在循环引用的问题,导致对象不能被正确识为垃圾

如下图,类似于死锁这种

方案2:可达性分析

JVM首先会从现有代码中能直接访问到的引用出发,尝试访问遍历所有能访问的对象,只要对象能访问到,都可以标记成可达。完成遍历之后,可达之外的东西,也就是不可达,可就是垃圾咯

更多的是看能不能到达,不能到达,就给你置空

2.释放对象的内存
1.标记-清除(直接释放)

这种问题,假如不去处理,还是挺严重的,内存碎片随着程序的运行越来越多,越来越碎,内存越来越难申请。

2.复制算法

复制算法,通过冗余的内存空间,把有效的对象复制到另一部分空间,来避免内存碎片

把一个内存,分成两份,用一份,丢一份,把左侧区域中,有效的对象,复制到右侧,接下来就可以使用右侧区域了,用了一段时间之后,也会有很多对象,也是相同的道理,把有效对象复制到左边,把右侧区域统一释放

3.标记整理

顺序表删除元素:搬运

实际有用的只有1,3,5

把没用的都迁移到后面,然后后面的元素进行删除。

4.JVM的垃圾回收机制

于是,设计JVM的大佬研究出了一个方法,集百家之长

​​​​​​​

按照对象的年龄,来制定不同的回收策略

GC是周期性进行扫描,每个对象没经过一轮GC,就称为涨了一岁。

新生代的扫描频次是比较高的,老年代的扫描频率就降低了​​​​​​​

但是上述情况中,还有一个特殊的情况“如果这个对象的体积特别的大”会直接进入老年代(大的对象不适合复制算法)

​​​​​​​

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

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

相关文章

供应链|顶刊MSOM论文解读:服务竞争下的库存共享

问题背景 在汽车、玩具等行业中,零售商之间的库存共享变得十分常见。库存共享可以解决由需求不确定导致的库存错配问题。如果零售商之间同意共享库存,那么当需求较少、自身库存过剩时,可以将过剩库存卖给其他零售商;反之&#xf…

图像分类(一) 全面解读复现AlexNet

解读 论文原文:http://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf Abstract-摘要 翻译 我们训练了一个庞大的深层卷积神经网络,将ImageNet LSVRC-2010比赛中的120万张高分辨率图像分为1000个不…

WinForms C# 导入和导出 CSV 文件 Spread.NET

使用 WinForms C# 和 VB.NET 导入和导出 CSV 文件 2023 年 11 月 17 日 使用 Spread.NET 直接在 .NET WinForms 应用程序中处理 CSV 文件。 Spread.NET可帮助您创建电子表格、网格、仪表板和表单。它包括一个强大的计算引擎,具有 450 多个函数以及导入和导出 Micros…

React+后端实现导出Excle表格的功能

最近在做一个基于Reactantd前端框架的Excel导出功能,我主要在后端做了处理,这个功能完成后,便总结成一篇技术分享文章,感兴趣的小伙伴可以参考该分享来做导出excle表格功能,以下步骤同样适用于vue框架,或者…

从0开始学习JavaScript--JavaScript 字符串与文本内容使用

JavaScript中的字符串和文本内容处理是前端开发中的核心技能之一。本文将深入研究字符串的创建、操作,以及文本内容的获取、修改等操作,并通过丰富的示例代码,帮助读者更全面地了解和应用这些概念。 JavaScript 字符串基础 字符串是JavaScr…

在VS Code中使用VIM

文章目录 安装和基本使用设置 安装和基本使用 VIM是VS Code的强大对手,其简化版本VI是Linux内置的文本编辑器,堪称VS Code问世之前最流行的编辑器,也是VS Code问世之后,我仍在使用的编辑器。 对VIM无法割舍的原因有二&#xff0…

Springboot 项目启动类放置位置

文章目录 Springboot 项目启动类放置位置springboot 默认包扫描机制启动类放在特定位置springboot 启动注解理解配置启动类扫描特定的包1、 ComponentScan2、利用 SpringBootApplication 注解的 scanBasePackages 属性 Springboot 项目启动类放置位置 如果我们使用 IDEA 或者 …

C++标准模板(STL)- 类型支持 (类型关系,检查两个类型是否相同,std::is_same)

类型特性 类型特性 类型特性定义一个编译时基于模板的结构&#xff0c;以查询或修改类型的属性。 试图特化定义于 <type_traits> 头文件的模板导致未定义行为&#xff0c;除了 std::common_type 可依照其所描述特化。 定义于<type_traits>头文件的模板可以用不完…

【Redux】Redux 基本使用

1. Redux 快速上手 Redux 是 React 最常用的集中状态管理工具&#xff0c;类似于Vue中的Pinia&#xff08;Vuex&#xff09;&#xff0c;可以独立于框架运行。 <button id"decrement">-</button> <span id"count">0</span> <…

Java - 位运算的基本原理和用途

Java - 位运算的基本原理和用途 前言一. Java 位运算基本操作1.1 按位与 &1.2 按位或 |1.3 按位异或 ^1.4 按位取反 ~1.5 位移运算1.5.1 左移运算符 <<1.5.2 右移运算符 >>1.5.3 无符号右移运算符 >>> 二. 位运算实际运用2.1 判断奇偶性&#xff08;&…

SpringSecurity5|12.实现RememberMe 及 实现原理分析

security/day08 这个功能大家还熟悉么&#xff1f;我们在登录网站的时候&#xff0c;除了让你输入用户名和密码&#xff0c;还会有个勾选框&#xff1a; 记住我&#xff01;&#xff01;&#xff01;不是让大家记住我哈。 值得一提的是&#xff0c;Spring Security 也提供了这个…

(C++)字符串相加

愿所有美好如期而遇 题目链接&#xff1a;415. 字符串相加 - 力扣&#xff08;LeetCode&#xff09; 思路 我们看到字符串长度可能到达一万&#xff0c;而且不允许使用处理大整数的库&#xff0c;也就是说&#xff0c;转成整数相加后再转成字符串是不可行的。 那么我们就让…