JVM基础面试题
JDK、JRE、JVM的关系
JVM内存模型以及分区情况和作用
如图所示:
黄色部分线程线程共享,蓝色部分线程私有。
方法区
存储类加载器的类信息,常量,静态变量等数据。
堆
存放实例对象,所有的对象(不包括直接内存对象、符合逃逸分析的对象和)和数组都在堆内存分配,JVM所管理的内存中最大的一块区域。
栈
Java方法执行的内存模型:存储局部变量表,操作数栈,动态链接,方法出口等信息。生命周期与线程相同
本地方法栈
作用与虚拟机栈类似。不同点本地方法栈为native方法执行服务,虚拟机栈为虚拟机执行的java方法服务。
程序计数器
当前线程所执行的行号指示器,是JVM内存区域最小的一块区域。执行字节码工作时就是利用程序计数器来选取下一条需要执行的字节码指令。
JVM对象创建流程
整体流程图如下
- 虚拟机遇到new指令,首先去检查这个指令的参数是否能在常量池中定位到这个类的符号引用,并检查这个符号引用的类是否已被加载,解析,初始化。
- 如果类已经加载直接分配内存,如果未加载,则先进行类的加载。
- 类加载检查通过之后,对新对象进行内存分配。
- 对象生成需要的内存大小在加载完成后便可完全确定,为对象分配空间等同于从Java堆内存中划分出一块确定大小的内存
- 内存大小划分分为两种情况:JVM内存是规整的(使用和未使用的内存分别放一边,中间放一个指针作为分界点指示器,这样分配就很简单,只需要将指针向空闲空间那边挪动与对象大小相同的距离,这就是“指针碰撞”)。JVM内存不是规整的(使用内存和未使用内存相互交错,这时候我们需要维护一张表,用于记录哪些内存可用,在分配时从列表中找到一个足够大的空间划分给对象,并更新到这张表中)
- JVM将内存空间初始化为0值,如果使用TLAB,就可以在TLAB分配的时候进行工作。
- JVM对对象进行必要设置。
- 执行完以上步骤之后从JVM来看一个对象基本上就完成了,但从Java程序代码绝对来看,对象创建才刚刚开始,需要执行init方法,按照程序中设定的初始化操作初始化,这时候一个真正的程序对象才生成了。
垃圾回收算法有哪些,他们的优缺点又是什么?
常见的垃圾回收算法有:
标记清除算法,复制算法,标记整理算法和分代收集算法
标记清除算法
包含两个阶段,标记和清除
标记阶段:确认所有需要回收的对象并做好标记
清除阶段:将标记节点标记不可用的对象清除
缺点:
标记和清除的效率都不高,会产生大量的碎片,导致频繁的回收。
复制算法
内存分为相等大小的两块,每次使用其中一块。当垃圾回收的时候把存活对象复制到另一块上,然后把这块内存整个清理掉
缺点:
浪费额外的内存作为复制区,当对象存活率较高时,复制算法效率会下降。
标记整理算法
不是把存活的对象复制到另一块内存,而是把存活对象往内存的一端移动,然后直接回收边界以外内存。
缺点:
算法复杂度大,执行步骤较多。
分代收集算法
目前大多数JVM垃圾收集器采用的算法,根据对象存活的生命周期将内存划分为若干不同的区域,一般情况将堆区划分为新生代、老年代和永久代。
老年代的特点是每次垃圾收集时只有少量对象被回收,而新生代的特点是每次垃圾收集会有大量对象被回收,那么根据不同代的特点采取最合适的收集算法。
如图:
Young区:存放新创建的对象,对象生命周期非常短,几乎用完可以立即回收,也叫eden区
Tenured:Young区经过多次回收后存活下来的对象将被移到改区,也称old区
Permanent:永久代,主要存放加载类的信息,生命周期长,几乎不会被回收。
缺点:
算法复杂,步骤较多。
简单介绍一下什么是类加载机制
Class文件由类加载器装载后,在JVM中形成一份描述Class结构的元信息对象,通过该元信息对象可以获取Class结构信息,如构造函数,方法,属性等。
虚拟机把描述类的数据从class文件加载到内存,并对数据进行校验,转换解析和初始化,最终形成可以被虚拟机直接使用的Java对象。
类加载过程是什么,简单描述下每个步骤?
包括:加载,验证,准备,解析,初始化
加载
查找并加载类的二进制数据
加载是类加载的第一个阶段,需要完成三件事情:
通过类的全限定名来获取其定义的二进制字节流
将字节流所代表的静态存储结构转换为方法区的运行时数据结构
在Java堆中生成一个代表这个类的java.lang.class对象,作为方法区中这些数据的访问入口。
验证
确保被加载的类的正确性
确保class文件的字节流中包含的信息符合当前虚拟机的规范,并且不会损害虚拟机自身的安全,包含四个验证动作:文件格式验证,元数据验证,字节码验证,符号引用验证。
准备
为静态变量分配内存,并将其初始化为默认值
正式为类的静态变量分配内存并设置类变量初始值阶段,这些内存都将在方法区中分配。
解析
符号引用转为直接引用
虚拟机将常量池中的符号引用替换为直接引用的过程,解析动作主要针对类或者接口、字段、类方法、接口方法、方法类型、方法句柄和调用点限定符7类符号引用进行。
初始化
类变量进行初始化
为类的静态变量赋予正确的初始值,JVM负责对类进行初始化,主要对类变量进行初始。
jvm类加载器有几种?分别作用是什么?
启动类加载器,扩展类加载器,程序类加载器
启动类加载器
引导类装入器是本地代码实现的类装入器,他负责将java_runtime_home/lib下面的类库加载到内存中。由于引导类加载器设计到虚拟机本地实现细节,开发者无法知己获取到启动类加载器的引用。
标准扩展类加载器
负责将java_runtime_home/lib/ext或者由系统变量java.ext.dir指定位置中的类库加载到内存中,程序员可以直接使用标准扩展类加载器
程序类加载器
负责加载用户路径classpath上的类库
双亲委派模式,有什么作用?
当一个类加载器需要加载一个类时,并不会立即自己去记载,而是首先委派给父类加载器去加载,父类加载器加载不了再给父类的父类去加载,一层一层往上委托,直到顶层加载器(启动类加载器),如果父类加载器反馈无法加载那么类加器才会自己去加载。(如下图所示)
作用:
1) 防止重复加载类。在JVM中,要唯一确定一个对象,是由类加载器和全类名两者共同确定的,考虑到各层级的类加载器之间仍然由重叠的类资源加载区域,通过向上抛的方式可以避免一个类被多个不同的类加载器加载,从而形成重复加载。
2) 安全。例如读者朋友定义了一个名为java.lang.Integer的类,而该类在核心库中也存在,借用双亲委派的机制,我们就能有效防止该自定义的同名类被加载,从而保护了平台的安全性。
怎么打破双亲委派模型?
JVM垃圾收集器有哪些?
主要分为以下七种,如图:
每种垃圾收集器之间有连线,表示他们可以搭配使用。
Serial收集器
Serial 是一款用于新生代的单线程收集器,采用复制算法进行垃圾收集。Serial 进行垃圾收集时,不仅只用一条线程执行垃圾收集工作,它在收集的同时,所有的用户线程必须暂停(Stop The World)。
就比如妈妈在家打扫卫生的时候,肯定不会边打扫边让儿子往地上乱扔纸屑,否则一边制造垃圾,一遍清理垃圾,这活啥时候也干不完。
如下是 Serial 收集器和 Serial Old 收集器结合进行垃圾收集的示意图,当用户线程都执行到安全点时,所有线程暂停执行,Serial 收集器以单线程,采用复制算法进行垃圾收集工作,收集完之后,用户线程继续开始执行。
ParNew 收集器
ParNew 就是一个 Serial 的多线程版本,其它与Serial并无区别。ParNew 在单核 CPU 环境并不会比 Serial 收集器达到更好的效果,它默认开启的收集线程数和 CPU 数量一致,可以通过 -XX:ParallelGCThreads 来设置垃圾收集的线程数。
如下是 ParNew 收集器和 Serial Old 收集器结合进行垃圾收集的示意图,当用户线程都执行到安全点时,所有线程暂停执行,ParNew 收集器以多线程,采用复制算法进行垃圾收集工作,收集完之后,用户线程继续开始执行。
Parallel Scavenge 收集器

Serial Old 收集器
Parallel Old 收集器
CMS收集器
G1 收集器
G1 收集器是 jdk1.7 才正式引用的商用收集器,现在已经成为 jdk9 默认的收集器。前面几款收集器收集的范围都是新生代或者老年代,G1 进行垃圾收集的范围是整个堆内存,它采用 “ 化整为零 ” 的思路,把整个堆内存划分为多个大小相等的独立区域(Region),在 G1 收集器中还保留着新生代和老年代的概念,它们分别都是一部分 Region,如下图:
每一个方块就是一个区域,每个区域可能是 Eden、Survivor、老年代,每种区域的数量也不一定。JVM 启动时会自动设置每个区域的大小(1M ~ 32M,必须是 2 的次幂),最多可以设置 2048 个区域(即支持的最大堆内存为 32M*2048 = 64G),假如设置 -Xmx8g -Xms8g,则每个区域大小为 8g/2048=4M。
为了在 GC Roots Tracing 的时候避免扫描全堆,在每个 Region 中,都有一个 Remembered Set 来实时记录该区域内的引用类型数据与其他区域数据的引用关系(在前面的几款分代收集中,新生代、老年代中也有一个 Remembered Set 来实时记录与其他区域的引用关系),在标记时直接参考这些引用关系就可以知道这些对象是否应该被清除,而不用扫描全堆的数据。
G1 收集器可以 “ 建立可预测的停顿时间模型 ”,它维护了一个列表用于记录每个 Region 回收的价值大小(回收后获得的空间大小以及回收所需时间的经验值),这样可以保证 G1 收集器在有限的时间内可以获得最大的回收效率。
如下图所示,G1 收集器收集器收集过程有初始标记、并发标记、最终标记、筛选回收,和 CMS 收集器前几步的收集过程很相似:
① 初始标记:标记出 GC Roots 直接关联的对象,这个阶段速度较快,需要停止用户线程,单线程执行。
② 并发标记:从 GC Root 开始对堆中的对象进行可达新分析,找出存活对象,这个阶段耗时较长,但可以和用户线程并发执行。
③ 最终标记:修正在并发标记阶段引用户程序执行而产生变动的标记记录。
④ 筛选回收:筛选回收阶段会对各个 Region 的回收价值和成本进行排序,根据用户所期望的 GC 停顿时间来指定回收计划(用最少的时间来回收包含垃圾最多的区域,这就是 Garbage First 的由来——第一时间清理垃圾最多的区块),这里为了提高回收效率,并没有采用和用户线程并发执行的方式,而是停顿用户线程。
适用场景:要求尽可能可控 GC 停顿时间;内存占用较大的应用。可以用 -XX:+UseG1GC 使用 G1 收集器,jdk9 默认使用 G1 收集器。
对象已死是什么意思
对象不可能在被任何途径使用
判断对象已死的方法有:引用计数法和可达性分析算法
什么情况会栈溢出
- 方法创建一个很大的对象,如:List,Array
- 是否产生循环调用,死循环
- 是否引用了较大的全局变量
Java四种引用类型,强软弱虚
强引用:new出的对象之类的,只要强引用还在永远不会被回收,因此强引用是造成 Java 内存泄漏的主要原因之 一。
软引用:当系统内存足够时它不会被回收,当系统内存空间不足时它会被回收。软引用通常用在对内存敏感的程序中。
Eden和Survivor的分配比例是多少,为什么?
cpu占用过高排查
top命令查看cpu占用最高程序
top -H -p [java进程id],找到cpu占用较高的线程id
计算java线程id的16进制值,因为后续用jstack看到的线程快照中,线程id为小写十六进制值
(1)可百度在线进制转换
(2)可使用windows自带的计算器,程序员模式,可转换十六进制
(3)Linux可使用命令:printf "%x\n" [线程_id]
使用命令 jstack [java进程pid] | grep [线程id十六进制值] -A 30(-A 30表示向下打印30行)
怎么打出线程栈信息
相关文章:

JVM基础面试题
JDK、JRE、JVM的关系 JVM Java虚拟机,它只识别.class类型文件,它能将class文件中的字节码指令进行识别并调用操作系统向上的API完成动作。 JRE Java运行时环境。它主要包含两部分:Jvm的标准实现和Java的一些基本类库。相对于JVM来说,JRE多出来…...
蓝桥杯官网填空题(平方末尾)
题目描述 本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。 能够表示为某个整数的平方的数字称为“平方数” 虽然无法立即说出某个数是平方数,但经常可以断定某个数不是平方数。 因为平方数的末位只可能是&#x…...

深入探究数据结构与算法:构建强大编程基础
文章目录 1. 为什么学习数据结构与算法?1.1 提高编程技能1.2 解决复杂问题1.3 面试准备1.4 提高代码效率 2. 学习资源2.1 经典教材2.2 在线学习平台2.3 学习编程社区 3. 数据结构与算法的实际应用3.1 排序算法3.2 图算法3.3 字符串匹配算法 4. 结论 🎉欢…...

Android 自定义View之圆形进度条
很多场景下都用到这种进度条,有的还带动画效果, 今天我也来写一个。 写之前先拆解下它的组成: 底层圆形上层弧形中间文字 那我们要做的就是: 绘制底层圆形;在同位置绘制上层弧形,但颜色不同ÿ…...
力扣(LeetCode)算法_C++——字母异位词分组
给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。 字母异位词 是由重新排列源单词的所有字母得到的一个新单词。 示例 1: 输入: strs [“eat”, “tea”, “tan”, “ate”, “nat”, “bat”] 输出: [[“bat”],[“nat”,“tan”…...

【LeetCode-中等题】59. 螺旋矩阵 II
文章目录 题目方法一:二维数组缩圈填数字方法二: 题目 方法一:二维数组缩圈填数字 定义四个边界条件,每转一圈,把数值填进去,然后缩小一圈,直到不满足条件位置 结束循环条件可以是: …...

错误: 找不到或无法加载主类 Main
在用git回退到上个版本后发现,无法运行项目并提示 错误: 找不到或无法加载主类 Main 可以看到Main前面的图标也是号。 查了半天没有解决,问了个大佬,大佬一下就解决掉了,本文记录下解决过程。 错误原因是编辑器无法找到代码位置&…...

【云原生】Kubeadmin安装k8s集群
目录 前言: 一 环境部署 1.1 服务器部署功能 1.2 环境准备(所有节点) 二 安装docker(所有节点) 三 所有节点安装kubeadm,kubelet和kubectl 3.1 定义kubernetes源 3.2 开机自启kubelet 四 部署K8S集…...

Java:Springboot和React中枚举值(数据字典)的使用
目录 1、开发中的需求2、实现效果3、后端代码4、前端代码5、接口数据6、完整代码7、参考文章 1、开发中的需求 开发和使用过程中,通常会涉及四个角色:数据库管理员、后端开发人员、前端开发人员、浏览者 数据库使用int类型的数值进行存储(e…...

git撤回 不小心 commit 进去的文件
我时候 我们可能讲一下不想提交的文件 不小心commit了进去 我们可以通过 git reset HEAD~来撤回刚才的添加记录...
qt之movetothread理解
基础概念 qt的下线程qthread,每个线程都有自己的事件循环exec。对象的线程上下文,每个对象都有自己的线程上下文,怎么理解呢,就是该对象在哪个线程创建,其线程上下文就是谁。每个qobject对象在创建时都有包含线程成员…...

深入剖析:垃圾回收你真的了解吗?
小熊学Java:https://www.javaxiaobear.cn/ 本文我们重点剖析 JVM 的垃圾回收机制。关于 JVM 垃圾回收机制面试中主要涉及这三个考题: JVM 中有哪些垃圾回收算法?它们各自有什么优劣? CMS 垃圾回收器是怎么工作的?有哪…...

ue5 物理场的应用
cable mat wpo particle 流体粒子 choas 破损 刚体 布料 cloud abp blueprint riggedbody 体积雾 毛发 全局的 局部的 非均匀的 连续变化的 也可以多个叠加 从全局 到 范围 除了vector还有scalar的值也就是0--1的黑白灰的值 但是最终输出的值的类型还是取决于这个 一…...

移动零00
题目链接 移动零 题目描述 注意点 将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序必须在不复制数组的情况下原地对数组进行操作 解答思路 采用双指针的思路,左指针指向已移动零的数组的尾部,右指针指向为移动零的数组的头部&…...
go初识iris框架(四) -框架设置操作
前言 iris(1) iris(2) iris(3) 框架设置操作 当我们的一个路径是xxx/user/info,xxx/user/login,xxx/user/register的时候,我们发现前面都有一个user,我们如果用/{data:string}这样的话这样导致我们的路径是灵活的,所以我们得用其他方法 这里我们的路径是以anime为…...
python基础语法(二)
目录 注释注释的语法注释行文档字符串 注释的规范 输入输出和用户的交互通过控制台输出通过控制台的输入 注释 注释的语法 注释行 python的注释:使用#开通的行都是注释 # 这是一行注释C语言的注释:使用//的都是注释 // 这是一行注释文档字符串 使用三引号引起来的称为文档…...

从本地到Gitee:一步步学习文件上传及解决常见报错问题
🙂博主:小猫娃来啦 🙂文章核心:一步步学习文件上传及解决常见报错问题 文章目录 安装git进入gitee官网,登录账号新建仓库先打开git命令行上传本地资源到仓库第一步:git init第二步:git add .第三…...

idea2018修改大小写提示(敏感)信息
操作步骤如下: File > Settings > Editor > Code Completion > Code Completion(默认是首字母,选为none将不区分大小写)...
Quartz.Net调度框架简介
Quartz.Net是一个功能强大的开源任务调度框架,它可以在C#应用程序中实现灵活、可靠的任务调度和定时作业。它的主要作用是允许开发人员按照预定的时间表执行各种任务,例如定期生成报表、发送电子邮件、备份数据等。 在C#中使用Quartz.Net进行配置、开发…...

HarmonyOS/OpenHarmony(Stage模型)应用开发组合手势(一)连续识别
组合手势由多种单一手势组合而成,通过在GestureGroup中使用不同的GestureMode来声明该组合手势的类型,支持连续识别、并行识别和互斥识别三种类型。 .GestureGroup(mode:GestureMode, …gesture:GestureType[]) mode:必选参数,为G…...
RestClient
什么是RestClient RestClient 是 Elasticsearch 官方提供的 Java 低级 REST 客户端,它允许HTTP与Elasticsearch 集群通信,而无需处理 JSON 序列化/反序列化等底层细节。它是 Elasticsearch Java API 客户端的基础。 RestClient 主要特点 轻量级ÿ…...

docker详细操作--未完待续
docker介绍 docker官网: Docker:加速容器应用程序开发 harbor官网:Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台,用于将应用程序及其依赖项(如库、运行时环…...
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以? 在 Golang 的面试中,map 类型的使用是一个常见的考点,其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...

Day131 | 灵神 | 回溯算法 | 子集型 子集
Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣(LeetCode) 思路: 笔者写过很多次这道题了,不想写题解了,大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...

【第二十一章 SDIO接口(SDIO)】
第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...

抖音增长新引擎:品融电商,一站式全案代运营领跑者
抖音增长新引擎:品融电商,一站式全案代运营领跑者 在抖音这个日活超7亿的流量汪洋中,品牌如何破浪前行?自建团队成本高、效果难控;碎片化运营又难成合力——这正是许多企业面临的增长困局。品融电商以「抖音全案代运营…...

【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)
可以使用Sqliteviz这个网站免费编写sql语句,它能够让用户直接在浏览器内练习SQL的语法,不需要安装任何软件。 链接如下: sqliteviz 注意: 在转写SQL语法时,关键字之间有一个特定的顺序,这个顺序会影响到…...
【git】把本地更改提交远程新分支feature_g
创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...
相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...

(转)什么是DockerCompose?它有什么作用?
一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用,而无需手动一个个创建和运行容器。 Compose文件是一个文本文件,通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...