JVM相关面试题

【面试题一】谈谈JVM内存模型

JVM内存区域的划分,之所以划分是为了JVM更好的进行内存管理。就好比一间卧室,这块放床,这块放个电脑桌,每块地方各自有各自的功能,床用来睡觉,电脑桌用来办公打游戏。而JVM划分的内存区域也是各自有各自的用处。首先当JVM启动时,会申请一块很大的空间,然后把这块空间分成几块较小的区域,如下图。

在这里插入图片描述

  1. 本地方法栈:是用来存储JVM内部的native方法之间调用的关系的。本地方法栈是JVM内部C++写的代码。
  2. 虚拟机栈:是给Java代码使用的栈,存储的是Java方法之间调用的关系。可以认为包含了多个元素,每个元素是一个方法,一个元素又可以称为“栈帧”,一个栈帧里会包含**“方法的入口地址、方法的返回地址、方法参数和局部变量”**,并且一个线程拥有一个栈,栈是线程私有的。
  3. 程序计数器:描述的是一个线程当前执行到了哪条指令,每个线程有一份。
  4. 堆:是JVM里最大的一块空间,存储的是NEW出的对象,类的成员变量。一个进程有一份,多个线程共享一份堆。
  5. 元数据区:在Java8之前是称为“方法区”的,在Java8之后才成为“元数据区”,存储的是类对象、静态成员变量和常量池。一个进程有一份,多个线程共享一份。

注意一下哈,此处总结为:栈存储的是局部变量,堆储存的是普通成员变量,元数据区存储的是静态成员变量。

【面试题二】谈谈JVM类的加载过程

类加载就是找到.class文件,然后把文件内容从硬盘里读取到内存中。大概流程如下:

在这里插入图片描述

  1. 加载:就是找到.class文件,打开文件,然后把文件内容从硬盘读到内存中,最后完成加载得到类对象。
  2. 验证:即验证.class文件的格式是否正确,.class文件是一个二进制的文件。在官方的虚拟机规范文档里有描述这个二进制文件长啥样。
  3. 准备:给类对象分配一个内存空间,也就是在元数据区里占个位置,此时会把静态成员变量初始为0值。
  4. 解析:初始化字符串常量,把符号引用转为直接引用。
  5. 初始化:此时才会真正的给类对象的内进行初始化,也就是进行成员的初始化,执行代码块、静态代码块和加载父类。

解释一下符号引用和直接引用是什么:字符串常量得有一块内存空间进行存放,然后使用一个引用来指向这个内存空间的起始地址,但是在类加载前,字符串常量是存放在.class文件里的,此时并未分配空间,也就是这个引用其实指向的是一个类似于“偏移量”或者是“占位符”的一个东西,这个就是“符号引用”。而当类加载后,字符串常量才会被真正的分配一个内存空间,此时这个引用才会指向这个内存空间的起始地址,这个就称为“直接引用”,这个过程就是“符号引用”转为“直接引用”。

【面试题三】一个类什么时候会被加载

只有当一个类被真正使用到了才会被加载,并不是当Java程序一启动就把所有类进行加载。比如进行构造类的实例,调用类的静态方法或者静态属性都会执行类加载。当使用子类时会先加载父类,并且一个类一旦被加载后,不会被重复加载。

【面试题四】谈谈双亲委派模型

​ 双亲委派模型描述的是如何找到.class文件。JVM提供了三个类加载器,BootStrapClassLoard负责加载标准库中的类,ExtensionClassLoard负载加载JVM扩展库中的类。(扩展库就是Java规范之外,由实现JVM的厂家提供的额外功能的库)ApplicationClassLoard负责加载第三方库的类和程序猿自定义的类。这三个类存在“父子关系”,即每个类里有个parent属性,这个属性里存储的是自己的“父·类加载器”。Application的父类加载器是Extension,Extension的父·类加载器是Bootstrap。

​ 当进行类加载时,会先Application开始,不过Application会把执行加载的任务交给自己的父类,只有当自己的父类加载完成后或者没有父类,自己才会真正的执行加载任务,于是此时任务交给了Extension,而Extension又把任务交给了BootStrap,最后BootStrap由于没有父类加载器,于是BootStrap开始执行类加载,去标准库里找到相关的类进行加载,如果没有找到剩余的类,就会把任务交给自己的子类加载,此时Extension会执行加载任务,会去扩展库中找到相关的类进行加载,最后把任务交给Application加载,去第三方库和自定义的类里找到并且加载,如果剩余的类没有找到,此时会报一个“类找不到”这样的异常。

​ **为什么会有这样的顺序?**之所以有这样的顺序是由于JVM的实现是按照类似于递归的方式实现的,于是就导致了从上到下又从下到上的顺序,其次也是为了保证BootStrap先加载,Application最后加载,这样可以避免程序猿自定义的一些类,引起了JVM内部bug。比如自定义写了个java.lang.String,按照上述流程就是先加载的是标准库里的String类,就不会导致JVM内部已经实现的代码出现bug。类加载器也可以自定义,并且可以存放在三个类加载器的任意位置。

【面试题五】谈谈Java的垃圾机制

GC垃圾回收就是把不用的内存给自动释放掉,这样的好处是写代码简单,不容易出错,但是会额外占用系统资源。如果当内存垃圾很多了,此时触发了GC操作,就会占用很多的系统资源,并且GC的有些操作会有一些锁操作,此时就会导致正常执行的业务代码无法执行,这种问题就称为“STW“问题(Stop The World)

GC进行垃圾回收是以“对象”单位回收的。此处可以把对象分为三类:一是正在使用的内存,二是不用了但未被回收的内存,三是未被分配内存的。像一部分在使用一部分未使用的对象是不会被回收的,比如一个对象里有些属性还在使用,而有些属性已经用完了。GC的具体工作流程是:先找到垃圾,然后进行释放。

  • 找到垃圾:使用的是可达性分析策略。JVM存有一份所有对象的名单,可达性分析就是把所有对象看作为一棵树,从根节点开始遍历,能访问到的就标记为“可达”,访问不到的标记为“不可达”,然后把这些不可达的对象当成垃圾给释放掉,可达性遍历会进行周期性的遍历。因为Java里的对象都是通过引用来指向进行访问内存的,而一个对象里的成员又可以通过引用指向另一个对象,因此就会构成一个类似于树形的结构,可达性分析的根节点/起点称为GCroots,GCroots可以是栈上的局部变量、常量池的对象和静态成员变量

  • 对象的释放/垃圾释放:进行垃圾的释放有以下几种策略

    1. 标记清除:标记清除就是把标记为垃圾的空间直接释放掉,简单高效,不过会导致内存碎片问题,由于Java申请空间都是连续性的,所以当申请一个较大的空间时,可能就会申请失败。

    2. 复制算法:解决了内存碎片的问题, 复制算法就是把一个空间分成两部分,每次只用一半的内存,然后当进行垃圾回收时,把不是垃圾的对象复制到另一半没有使用的内存里,由于对象是按顺序复制过来的,所以不会有内存碎片问题。但是复制算法的成本比较高,当垃圾较少时,有效对象多,此时触发复制算法,复制的成本就比较大。

      在这里插入图片描述

      进行了复制算法,把左侧对象1(垃圾)进行了删除,此时右侧内存是顺序存放的,所以内存空间是连续的,下次比如对象2变成了垃圾,就会把对象3复制到左侧内存空间,然后直接把对象2进行释放。

      在这里插入图片描述

    3. 标记整理:标记整理解决了空间利用率低的问题,类似于顺序表删除元素或者搬运元素。比如内存里有1、2、3、4、5、6此时2、4、6为垃圾,就把3、5往前进行搬运,把2、4覆盖掉,最后把6直接释放。

      在这里插入图片描述

    4. 分代回收:基于前面几种策略,设计出一个复合型的策略,即把垃圾回收分为不同的场景,每个场景使用不同的算法。Java对象的生命周期一般比较长,要么就很短,所以可以根据生命周期的长短,引入一个“年龄”的概念,单位是熬过GC的轮次,即当GC扫描一轮后,当前对象存活下来就把年龄+1,每个刚NEW出来的对象年龄为0。JVM把堆划分出一系列的区域,先把一整个空间划分为两部分,一部分为新生代,另一部分为老年代,在新生代里划分出一个较大的伊甸区,和两个同等大小的幸存区,伊甸区存放刚NEW出来的新对象,当熬过一轮GC后,使用复制算法把对象复制到第一个幸存区,到了幸存区后,当前对象需要继续接受GC周期性的扫描,当第二次熬过GC轮次后,从第一个幸存区复制到第二个幸存区,这样来回两个幸存区复制,当对象的年龄达到15时,就复制到老年代,进入老年代后,GC就会降低扫描的频率,因为当进入老年代说明当前对象生命周期很长,短时间内不会成为垃圾,当老年代里的对象称为垃圾时,会使用标记整理的策略进行垃圾释放。

    在这里插入图片描述

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

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

相关文章

SpringBoot快速入门(黑马学习笔记)

需求 需求:基于SpringBoot的方式开发一个Web应用,浏览器发起请求/hello后,给浏览器返回字符串"Hello World~"。 开发步骤 第一步:创建SpringBoot工程项目 第二步:定义HelloController类,添加方…

【Python_11】Python基础语法(数据容器之字典详解)

文章目录 概述Python中的数据容器字典1.1 定义字典1.2取值与改值1.3 遍历字典1.3.1 遍历字典的key1.3.2 遍历字典的值1.3.3 遍历字典键值对1.3.4 sorted()函数排序 1.4 字典常用方法 概述 数据容器是用来存储和组织数据的数据结构和对象。可以以不同的方式存储和操作数据&…

主数据管理是数字化转型成功的基石——江淮汽车案例分享

汽车行业数字化转型的背景 在新冠疫情导火索的影响下,经济全球化政治基础逐渐动摇。作为全球最大的汽车市场,我国的汽车市场逐渐由增量转为存量市场。 在数字化改革大背景下,随着工业4.0时代的到来,江淮汽车集团力争实现十四五数…

goland配置新增文件头

参考: goland函数注释生成插件 goland函数注释生成插件_goland自动加函数说明-CSDN博客 GoLand 快速添加方法注释 GoLand 快速添加方法注释_goland批量注释-CSDN博客 goland 如何设置头注释,自定义author和data goland 如何设置头注释,自定…

苹果上架App被拒绝的原因

苹果上架App被拒绝的原因有很多种,主要包括以下几个方面: 1.功能问题:苹果认为你的App存在功能问题,不符合App Store的要求。比如,你的App可能存在漏洞,会影响用户体验或者安全性,或者涉及到隐…

现代化数据架构升级:毫末智行自动驾驶如何应对年增20PB的数据规模挑战?

毫末智行是一家致力于自动驾驶的人工智能技术公司,其前身是长城汽车智能驾驶前瞻分部,以零事故、零拥堵、自由出行和高效物流为目标,助力合作伙伴重塑和全面升级整个社会的出行及物流方式。 在自动驾驶领域中,是什么原因让毫末智行…

【可实战】被测系统业务架构、系统架构、技术架构、数据流、业务逻辑分析

一、为什么要学习 更深的理解业务逻辑(公司是做什么的?它最重要的商务决策是什么?它里面的数据流是怎么做的?有哪些业务场景?考验你对这家公司、对所负责业务的熟悉程度。公司背后服务器用什么软件搭建的?…

js 对象总结

文章目录 1、创建对象的6种方式总结一、new 操作符 Object 创建对象二、字面式创建对象 2、js 如何判断对象是否为空3、获取对象长度4、js 遍历对象的 5 种方法1、for … in2、Object.keys(obj)3、Object.values(obj)4、Object.getOwnPropertyNames(obj)5、使用Reflect.ownKey…

领先科技2024年3月5-7日第12届国际生物发酵展-宁泰橡塑

参展企业介绍 湖南宁泰橡塑有限公司(简称“宁泰”)位于国家 级湖南省浏阳经济技术开发区,距离省会城市长沙35公里,距离黄花国际机场18公里,交通便利,区位和地缘优势明显。宁泰是一家专业从事卫生级橡塑制品…

通过 Java 中 5 种流行的方法提取电子邮件

在开发电子邮件处理应用程序时,建立一种从收件箱中提取消息的有效机制对于可靠、及时的传递和可访问性至关重要。处理不断增长的传入消息的组织和企业尤其赞赏它。在本文中,我们将探讨如何利用 Java 库的强大功能,通过 POP3、IMAP、EWS、Grap…

Linux系统部署前后端分离项目

一、Nginx简介 1.1 什么是nginx? Nginx(发音同"engine x")是一个高性能的反向代理和 Web 服务器软件,最初是由俄罗斯人 Igor Sysoev 开发的。Nginx 的第一个版本发布于 2004 年,其源代码基于双条款 BSD 许可证发布&am…

Mysql常见函数和用法(重点)

目录 where子句中经常使用的运算符 order by 子句排序查询结果 合计 (count) 统计函数(sum) 求平均值函数(avg) 最大值(max)和最小值(min) groupby子句对列进行分组 字符串相关函数​编辑 数学相关…

华为ipv6 over ipv4 GRE隧道配置

思路: PC1访问PC2时,会先构造源ipv6为2001:1::2,目的IPV6为2001:2::2的ipv6报文,然后查看PC1的路由表,发送到R1,r1接收后,以目的IPV6地址2001:2::2查询IPV6路由表,出接口为tun0/0/0…

jQuery引入及下载方法

jQuery引入及下载方法 目录 jQuery引入及下载方法【方法1】cdn引入【方法2】下载本地文件 【方法1】cdn引入 直接在head引入jq <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title>&…

面试redis篇-13Redis为什么那么快

Redis是纯内存操作,执行速度非常快采用单线程,避免不必要的上下文切换可竞争条件,多线程还要考虑线程安全问题使用I/O多路复用模型,非阻塞IOI/O多路复用模型 Redis是纯内存操作,执行速度非常快,它的性能瓶颈是网络延迟而不是执行速度, I/O多路复用模型主要就是实现了高效…

消息中间件篇之Kafka-消息不丢失

一、 正常工作流程 生产者发送消息到kafka集群&#xff0c;然后由集群发送到消费者。 但是可能中途会出现消息的丢失。下面是解决方案。 二、 生产者发送消息到Brocker丢失 1. 设置异步发送 //同步发送RecordMetadata recordMetadata kafkaProducer.send(record).get();//异…

python Matplotlib Tkinter-->tab切换1

环境 python:python-3.12.0-amd64 包: matplotlib 3.8.2 pillow 10.1.0 import matplotlib.pyplot as plt from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk import tkinter as tk import tkinter.messagebox as messagebox import …

Unity发布webgl获取浏览器的URL

Unity发布webgl获取浏览器的URL Unity发布webgl之后获取浏览器的url 在unity中创建文件夹Plugins&#xff0c;然后添加添加文件UnityGetBrowserURL.jslib var GetUrlFunc {//获取地址栏的URLStringReturnValueFunction: function () {var returnStr window.top.location.hre…

软件无线电SDR加人工智能算法实现无人机频谱探测

通用软件无线电接收机作为传感器实时接收探测无线电信号&#xff0c;加上深度学习算法实现频谱识别&#xff0c;(https://img-blog.csdnimg.cn/5a6c4d89a047453a94f763f4e67aeb17.png)

折腾Chrome插件,让内容脚本与文本交互~

我们要用内容脚本&#xff08;content scripts&#xff09;来给插件装上一双慧眼&#xff0c;让它能在你浏览的页面上跳来跳去&#xff0c;和文字做游戏。这就像给插件喂了一颗智慧豆&#xff0c;让它变得聪明起来&#xff0c;能够直接和网页内容打招呼啦&#xff01; 在本章&…
最新文章