【JVM】之常见面试题

文章目录

  • 1.JVM中的内存区域划分
  • 2.JVM的类加载机制
    • 2.1 加载
    • 2.2 验证
    • 2.3 准备
    • 2.4 解析
    • 2.5 初始化
    • 2.6 类加载的时机
  • 3 类加载器
  • 4.双亲委派模型
  • 5.JVM中的垃圾回收策略
    • 5.1 找谁是垃圾
      • 5.1.1 引用计数法
      • 5.1.2 可达性分析法
    • 5.2 释放垃圾
      • 5.2.1 标记清除算法
      • 5.2.2 复制算法
      • 5.2.3 标记整理算法
      • 5.2.4 分代算法

1.JVM中的内存区域划分

JVM就是一个Java进程,Java进程会从操作系统这里申请一大块内存空间,给Java代码来使用。
而这一大块内存空间又可以进一步细分为以下几个最核心的内存区域:

  • 堆:存放的是new出来的对象,即成员变量。
  • 栈:存放的是方法与方法之间的调用关系,即局部变量。
  • 方法区(旧)/元数据区(新):存放的是类加载之后的类对象(.class,Test.class),即静态变量。

这块的主要考点就是给一段代码,判断某个变量处于内存中的哪个位置,需要注意是的,我们是通过变量的形态(成员变量,局部变量,静态变量)来判断,而不是通过变量的类型来判断。

例如下面的例子:

  void func() {Test t = new Test();}

在这里插入图片描述
接下来我们就系统的介绍一下JVM运行时数据区,也叫JVM的内存布局。按照 Java 的虚拟机规范,可以细分为程序计数器、虚拟机栈、本地方法栈、堆、方法区等,如下图:
在这里插入图片描述
其中堆和方法区在一个JVM进程中只有一份,而栈(虚拟机栈和本地方法栈)和程序计数器则是有多份的,每一个线程有一份。

  • 程序计数器 : 也叫PC寄存器,用途是记录当前程序执行到哪个指令了,它是一个简单的long类型变量,里面存了一个内存地址,这个内存地址就是下一个要执行的字节码的内存地址。
  • Java虚拟机栈:通常就是指”栈“,它的生命周期和线程一样,当线程执行一个方法时,会创建一个对应的栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口等信息,然后栈帧会被压入栈中。当方法执行完毕后,栈帧会从栈中移除。
  • 本地方法栈:是给JVM内部的本地方法使用的(JVM内部通过C++实现的方法)。
  • :堆(heap)是 JVM 中最大的一块内存区域,被所有线程共享,在 JVM 启动时创建,主要用来存储对象的。
  • 方法区:用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。方法区也是所有线程共享的。

2.JVM的类加载机制

.class 文件需要加载到虚拟机中之后才能运行和使用,类加载的过程就是将.class文件加载到内存中得到类对象的过程。其中类加载的过程分为五步,即加载→验证→准备→解析→初始化,如下图所示:
在这里插入图片描述

2.1 加载

加载阶段就是查找并加载类的二进制数据(.class文件),在加载阶段,JVM做三件事情:

  1. 通过一个类的全限定名来获取定义此类的二进制字节流。
  2. 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。
  3. 在内存中生成一个代表这个类的 java.lang.Class 对象,作为方法区这个类的各种数据的访问入口。

2.2 验证

这一阶段的目的是确保 Class 文件的字节流中包含的信息符合《Java 虚拟机规范》的全部约束要求,保证这些信息被当作代码运行后不会危害虚拟机自身的安全。验证包括了:文件格式验证(二进制文件)、字节码验证,符号引用验证

2.3 准备

在准备阶段,JVM会给类对象分配内存空间并设置初始值,初始值为数据类型的默认初始值,如0,0L,false,null等。

2.4 解析

解析阶段是虚拟机将常量池中的符号引用替换为直接引用的过程。

其中符号引用就是字符串常量,它在.class文件中已经存在了,但它们之间只知道彼此的相对位置(偏移量),并不知道自己在内存中的实际位置,而当真正加载到内存中的时候,就会把字符串常量填充到特定的位置上,字符串常量之间的相对位置还是一样的,但此时它们有了实际的内存地址,此时的字符串常量就是直接引用了(Java中的普通引用)。

2.5 初始化

初始化阶段就是针对类对象进行初始化(初始化静态成员,执行静态代码块,如果该类还有父类还需加载它的父类)。

2.6 类加载的时机

JVM 启动的时候,并不会一次性加载所有的类,而是根据需要去动态加载。也就是说,大部分类在具体用到的时候才会去加载,这样对内存更加友好。
那么什么是需要的时候呢?

  1. 创建了这个类的实例
  2. 使用了这个类的静态方法/静态属性
  3. 使用子类,也会触发父类的加载

3 类加载器

在介绍双亲委派模型之前,我们需要先知道JVM加载类时需要用到一组特殊的模块,即类加载器。
类加载器(ClassLoader)用于动态加载 Java 类到 Java 虚拟机中。主要有四种类加载器:

  1. 启动类加载器(Bootstrap ClassLoader)负责加载Java标准库中的类。

  2. 扩展类加载器(Extension ClassLoader):负责加载一些非标准的但是Sum/Oracle扩展的类

  3. 应用程序类加载器(Application ClassLoader):负责加载项目中自己写的类以及第三方库中的类。

  4. 用户自定义类加载器 (User-Defined ClassLoader),我们可以通过继承java.lang.ClassLoader类来创建自己的类加载器。

4.双亲委派模型

在上面我们介绍了JVM类加载的过程,而这就不得不提到一个重要的考点了——双亲委派模型。
它发生在第一步加载中找.class文件的时候,是 Java 类加载机制中的一个重要概念。这种模型指的是一个类加载器在尝试加载某个类时,首先会将加载任务委托给其父类加载器去完成。只有当父类加载器无法完成这个加载请求(即它找不到指定的类)时,子类加载器才会尝试自己去加载这个类。 如下图所示:

在这里插入图片描述

  • 当一个类加载器需要加载某个类时,它首先会请求其父类加载器加载这个类。
  • 这个过程会一直向上递归,也就是说,从子加载器到父加载器,再到更上层的加载器,一直到最顶层的启动类加载器(Bootstrap ClassLoader)。
  • 启动类加载器会尝试加载这个类。如果它能够加载这个类,就直接返回;如果它不能加载这个类(因为这个类不在它的搜索范围内),就会将加载任务返回给委托它的子加载器。
  • 子加载器接着尝试加载这个类。如果子加载器也无法加载这个类,它就会继续向下传递这个加载任务,依此类推。
  • 这个过程会继续,直到某个加载器能够加载这个类,或者所有加载器都无法加载这个类,最终抛出 ClassNotFoundException。

5.JVM中的垃圾回收策略

垃圾回收(Garbage Collection,GC),顾名思义就是释放垃圾占用的空间,防止内存爆掉。有效的使用可以使用的内存,对内存堆中已经死亡的或者长时间没有使用的对象进行清除和回收。
而垃圾回收之前我们需要先清楚谁是垃圾,谁不是垃圾,即GC分为了两步,先是找谁是垃圾,再对垃圾进行释放。

5.1 找谁是垃圾

常用的垃圾判断算法有引用计数算法,可达性分析算法。

5.1.1 引用计数法

引用计数法:给对象增加一个引用计数器,每当有一个地方引用该对象时,计数器+1,当引用失效时,计数器-1,任何时候计数器为 0 的对象就是不可能再被使用的。
优点:实现简单,效率高
缺点:无法解决循环引用的问题

5.1.2 可达性分析法

这个算法的基本思想就是通过一系列的称为 “GC Roots” 的对象作为起点,从这些节点开始向下搜索,节点所走过的路径称为引用链,当一个对象到 GC Roots 没有任何引用链相连的话,即从 GC Roots 到该对象节点不可达,则证明该对象是需要垃圾收集的。
在这里插入图片描述
可以作为GC Roots的对象:

  • 栈上的局部变量(每个栈的每个局部变量都是起点)
  • 常量池中引用的对象
  • 方法区中,静态变量引用的对象

5.2 释放垃圾

在确定了哪些垃圾可以被回收后,垃圾收集器要做的事情就是进行垃圾回收,如何高效地进行垃圾回收呢?

5.2.1 标记清除算法

标记清除算法,分为 2 部分,先把内存区域中的这些对象进行标记,哪些属于可回收的标记出来,然后把这些垃圾拎出来清理掉。
在这里插入图片描述

优点:实现简单。

缺点:产生大量不连续的内存碎片。当我们想申请一块连续的较大的内存时,可能就申请不到。

5.2.2 复制算法

在标记清除算法上演化而来的,用于解决标记清除算法的内存碎片问题。它将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。
在这里插入图片描述
优点:执行效率高,没有内存碎片的问题。

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

5.2.3 标记整理算法

标记整理算法,标记过程仍然与标记清除算法一样,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,再清理掉端边界以外的内存区域。
在这里插入图片描述
优点:解决了内存碎片问题,比复制算法空间利用率高。

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

5.2.4 分代算法

当前虚拟机的垃圾收集都采用分代收集算法,是根据对象存活周期的不同将内存分为几块。一般将 Java 堆分为新生代和老年代,这样我们就可以根据各个年代的特点选择合适的垃圾收集算法。
由于新生代存放的大部分数据是朝生夕死的,所以新生代使用的是效率最高的复制算法;而老生代使用的是标记-清除或标记-整理算法,如果标记-清除可以满足需要那么就使用效率更好的标记-清除算法,如果标记-清除算法不能满足需要就使用标记-整理算法。

在这里插入图片描述
今天的分享到这里就结束了,感谢支持!

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

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

相关文章

CorelDRAW2024永久破解版下载安装全教程!

在设计领域,精准和专业是至关重要的要素。随着技术的飞速发展,设计师们对软件的选择也越发严苛。CorelDRAW 2024中文版及其2024终身永久版、破解版,因其强大的功能和便捷的使用体验,成为了设计师们的首选之一。本文将深入探讨这一…

网络编程入门

文章目录 网络编程入门计算机网络基础计算机网络发展史TCP/IP模型网络应用模式 基于HTTP协议的网络资源访问HTTP(超文本传输协议)JSON格式requests库 基于传输层协议的套接字编程TCP套接字UDP套接字 网络应用开发发送电子邮件发送短信 网络编程入门 计算…

大模型时代已至,产品经理如何紧跟时代步伐?

前言 在数字化浪潮的推动下,人工智能领域正迎来一场技术革命,而大模型技术的崛起无疑是这场革命中的明星。作为产品经理,我们不仅要洞察市场趋势,更要紧跟技术发展,以创新的思维和敏锐的洞察力,引领产品走…

YOLOv5+单目测距(python)

YOLOv5单目测距(python) 1. 相关配置2. 测距原理3. 相机标定3.1:标定方法13.2:标定方法2 4. 相机测距4.1 测距添加4.2 细节修改(可忽略)4.3 主代码 5. 实验效果 相关链接 1. YOLOV7 单目测距(p…

每日一题——Python实现PAT甲级1112 Stucked Keyboard(举一反三+思想解读+逐步优化)五千字好文

一个认为一切根源都是“自己不够强”的INTJ 个人主页:用哲学编程-CSDN博客专栏:每日一题——举一反三Python编程学习Python内置函数 Python-3.12.0文档解读 目录 我的写法 时间复杂度 空间复杂度 总结 我要更强 代码分析 时间复杂度 空间复杂度…

组织创新|AI赋能敏捷实践,助力企业敏捷转型

在工业5.0时代,随着项目变得越来越复杂,对效率的需求也在增长,致力于敏捷转型的组织正在寻求创新的解决方案来应对常见的挑战:工作量不平衡、低效的任务分配和知识孤岛等等。对此,AI等尖端技术的潜力可以帮助实现更高效…

测试多模态模型MiniCPM

目录 模型参考信息: 文件目录: 使用图片: 执行结果: 让模型用中文输出: 评价 模型参考信息: https://huggingface.co/openbmb/MiniCPM-Llama3-V-2_5 文件目录: 使用图片: h…

HCIA14 DHCP 实验

动态主机配置协议 DHCP(Dynamic Host Configuration Protocol)由 RFC 2131 定义,采用客户端/服务器通信模式,由客户端(DHCP Client)向服务器(DHCP Server)提出配置申请,服…

HTML--给网站添加已运行时间的统计

原文网址&#xff1a;HTML--给网站添加已运行时间的统计_IT利刃出鞘的博客-CSDN博客 简介 本文介绍怎么给自己网站添加已经运行了多长时间。 代码 <html lang"cn"><head><meta http-equiv"Content-Type" content"text/html;charse…

KafkaQ - 好用的 Kafka Linux 命令行可视化工具

鉴于并没有在网上找到比较好的linux平台的kafka可视化工具&#xff0c;今天为大家介绍一下自己开发的在 Linux 平台上使用的可视化工具KafkaQ 虽然简陋&#xff0c;主要可以实现下面的这些功能&#xff1a; 1&#xff09;查看当前topic的分片数量和副本数量 2&#xff09;查…

【GlobalMapper】去除数据黑边

tif数据加载出来有这种黑色的边框&#xff0c;使用 Global Mapper切片之后&#xff0c;会有那种黑色的色块加载出来 影像黑边出现的原因&#xff1a; 通常&#xff0c;由于影像格式、像素深度、无效值、背景值等原因&#xff0c;会产生黑边或者白边&#xff0c;给影像的拼接或…

【图书推荐】《Vue.js 3.x+Element Plus前端开发实战》

本书重点 Element Plus是一套采用Vue.js 3.x实现的UI组件库&#xff0c;它为开发者、设计师和产品经理提供了配套设计资源&#xff0c;可以帮助网站快速成型。 本书详解Vue.js 3.x和Element Plus开发方法&#xff0c;配套源码、PPT课件。 内容简介 本书分为两篇&#xff0c…

d3dcompiler_43.dll是什么文件?怎么高效率的解决d3dcompiler_43.dll丢失问题

d3dcompiler_43.dll是什么文件&#xff1f;当你知道d3dcompiler_43.dll这个文件名字的时候&#xff0c;相信你是遇到了d3dcompiler_43.dll丢失的问题了&#xff01;所以才会这样问&#xff0c;其实这就是一个普通的dll文件&#xff0c;对于电脑系统有着至关重要的作用&#xff…

干货分享:宏集物联网HMI通过S7 MPI协议采集西门子400PLC数据

前言 为了实现和西门子PLC的数据交互&#xff0c;宏集物联网HMI集成了S7 PPI、S7 MPI、S7 Optimized、S7 ETH等多个驱动来适配西门子200、300、400、1200、1500、LOGO等系列PLC。 本文主要介绍宏集HMI通过S7 MPI协议采集西门子400PLC数据的操作步骤&#xff0c;其他协议的操作…

【面经总结】Java基础 - IO

序列化 什么是序列化和反序列化&#xff1f; 序列化&#xff1a;将对象转换为二进制数据 反序列化&#xff1a;将二进制数据转换为对象 目的&#xff1a;方便网络传输、持久化保存 Java 是怎么实现序列化的&#xff1f; Java 通过对象输入输出流来实现序列化和反序列化&a…

tp6+swoole+mysql+nginx+redis高并发优化

1.服务器 IDC机房提供的物理机&#xff1a;单机 40核&#xff0c;64G内存&#xff0c;带宽100M&#xff0c; 2.redis 7.2配置 timeout600 #空闲连接超时时间,0表示不断开 maxclients100000 #最大连接数 3.Mysql 5.7配置&#xff0c;按宝塔16-32G优化方案并调整&#xff1a;…

通用大模型VS垂直大模型,相辅相成!

1.通用大模型&#xff1a; 如OpenAI的GPT系列、Google的PaLM等&#xff0c;因其广泛的训练数据来源和强大的泛化能力&#xff0c;展现出在多种任务和场景中的应用潜力。它们能够处理从文本生成、代码编写到语言翻译等多种复杂任务&#xff0c;适应性强&#xff0c;减少了针对单…

第二届京津冀现代商贸物流金融创新发展百人大会将于6月16日在廊坊举行

编辑&#xff5c;Ray 物流是实体经济的“筋络”&#xff0c;联接生产和消费、内贸和外贸&#xff0c;必须有效降低全社会物流成本&#xff0c;增强产业核心竞争力&#xff0c;提高经济运行效率。《京津冀协同发展规划纲要》赋予河北“三区一基地”的功能定位&#xff0c;建设全…

第十七章 策略模式

目录 1 策略模式概述 2 策略模式原理 3 策略模式实现 4 策略模式应用实例 5 策略模式总结 1 策略模式概述 策略模式(strategy pattern)的原始定义是&#xff1a;定义一系列算法&#xff0c;将每一个算法封装起来&#xff0c;并使它们可以相互替换。策略模式让算法可以独立…

java实现文件的压缩及解压

一、起因 开发中需要实现文件的压缩及解压功能&#xff0c;以满足某些特定场景的下的需要&#xff0c;在此说下具体实现。 二、实现 1.定义一个工具类ZipUtils,实现文件的压缩及解压&#xff0c;代码如下&#xff1a; import java.io.*; import java.nio.charset.Charset; impo…