Java面试题——第三篇(JVM)

1. 什么情况下会发生栈内存溢出

栈是线程私有的,他的生命周期和线程相同,每个方法在执行的时候都会创建一个栈帧,用来存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机中从入栈到出栈的过程。
栈内存溢出是指线程请求的栈深度大于虚拟机所允许的最大深度,则会抛出StackOverflow异常。
另一个可能是栈中引用了大的变量,导致OOM异常。

2. JVM内存结构,Eden和Survivor的比例

在这里插入图片描述

内存结构

  • 程序计数器: 当前线程执行的字节码的行号指示器,是线程私有的,也是唯一一个不会发生OOM异常的区域。
  • Java虚拟机栈:也是线程私有的,保存方法调用的动态链接、操作数、局部变量等信息,方法调用就是虚拟机栈出栈入栈的过程。
  • 本地方法栈:线程私有的,和虚拟机栈类似,只是保存的是对于native方法的调用。
  • 堆:所有线程共享,Java虚拟机中管理的内存最大的一个区域,所有线程共享的区域,唯一目的是存放对象实例。也是垃圾回收的主要区域。
  • 方法区:线程共享,存放虚拟机加载的类信息、常量、静态变量等数据。
  • 运行时常量池:是方法区的一部分,存放编译器生成的各种字面量和符号引用。
  • 直接内存:并不是虚拟机运行时数据区域的一部分,使用Native函数直接分配堆外内存,通过一个存储在Java堆中的DirectByteBuffer对象作为这块内存的引用进行操作。避免了在Java堆和Native堆中来回复制数据。

Eden和Survivor比例

JVM对堆进行分代,新生代分为三个部分,1个Eden区、2个Survivor区。默认比例为8:1:1。一般情况下,新创建的对象都会被分配到Eden区(一些大对象除外)。这些对象经过一次Minor GC后,如果仍然存在,将会被移到Survivor区。对象每次熬过一次Minor GC,年龄就会增加1岁。当年龄增加到一定程度时,将会被移动到老年代.

3. JVM为什么要分为新生代、老年代和持久代。新生代中为什么要分为Eden区域和Survivor区。

  • 堆内存是虚拟机管理的内存中最大的一块,堆内存区域划分,主要是为了提高对象内存分配和回收效率。
  • 新创建的对象在新生代中分配,经过多次回收仍然存活的对象放入老年代。静态变量、类信息存放在永久代中。大部分对象都是朝生夕死的,只需要在新生代中频繁执行Minor GC,老年代中对象生命周期长,内存回收的效率相对较低,不需要频繁进行回收,永久代中回收效果太差,一般不进行回收。
  • 另外,分代以后可以根据不同的区域执行不同的垃圾回收算法。例如,新生代通常采用 标记-复制算法 , 老年代通常采用 标记-清除-整理 算法。

新生代分为Eden区、From Survivor区、To Survivor区,默认比例为8:1:1。划分的目的是因为JVM采用复制算法来回收新生代,设置这个比例是为了充分利用内存空间,减少浪费。新生成的对象在Eden区分配,当Eden区域没有足够内存时触发Minor GC,对象进入Survivor区域。

4. JVM中一次完整的GC流程是什么样,对象如何晋升到老年代,介绍几种主要的JVM参数。

完整GC流程

  • GC开始时,对象只存在于Eden区和From Survivor区域,To Survivor是空白的保留区域。GC进行时,Eden中所有存活的对象会被复制到To Survivor区域,而在From Survivor区域的对象,根据年龄决定去向,如果年龄+1大于15,则晋升到老年代,否则,进入To Survivor区域。接着,清空Eden区域和From Survivor区域。接着,From Survivor和To Survivor区域交换角色,即,To Survivor变成From Survivor。

对象晋升到老年代的几种可能:

  • 当对象达到成年,经过15次GC,对象晋升到老年代。
  • 大的对象直接在老年代创建。
  • 新生代的Survivor空间内存不足时,对象可能直接晋升到老年代。

主要的JVM参数
默认情况下,JVM初始分配的堆内存大小是物理内存的1/64,最大分配的堆内存大小是物理内存的1/4.

  • -Xms:初始堆大小
  • -Xmx:堆最大内存
  • -Xss:栈内存
  • -XX:PermSize 初始化永久代内存
  • -XX:MaxPermSize 最大永久代内存
  • -XX:NewSize 设置年轻代初始值
  • -XX:MaxNewSize 设置年轻代最大值

5. 介绍几种垃圾收集器,各自的优缺点,重点介绍cms和G1收集器,包括原理,流程,优缺点。

  1. 串行收集器(Serial 收集器)
  • 工作原理:串行收集器是工作在新生代的单线程垃圾收集器。只会使用一个CPU或者一个收集线程来完成垃圾回收工作,在进行垃圾收集时,会暂停所有用户线程,直到垃圾收集结束。
  • 优点:简单高效,开销低
  • 缺点:进行垃圾收集时需要暂停所有应用线程,对于需要高响应性的应用来说是不可接受的。
  1. ParNew收集器
  • 工作原理:ParNew收集器是串行收集器的多线程版本;除了使用多线程外,其收集算法、STW、对象分配规则、回收策略和Serial收集器完全一样。
  • 优点:提高吞吐量,减少暂停时间。能和CMS收集器配合工作,在Server模式下,是许多新生代收集器的首选。
  • 缺点:单CPU环境中可能不如串行收集器,随着CPU数量增加,线程交互的开销可能成为性能瓶颈。
  1. Parallel Scavenge收集器
  • 工作原理:Parallel Scavenge收集器也是一个使用复制算法,多线程,工作于新生代的垃圾收集器。他关注的是吞吐量,而CMS关注的是停顿时间。
  • 优点:提高吞吐量,减少暂停时间。
  • 缺点:不适用于对停顿时间要求极高的应用。
  1. CMS收集器
  • 工作原理:CMS收集器是基于“标记-清除”算法实现的并发收集器。
  • 工作流程:
  1. 初始标记:标记出和GC Roots直接相连的对象,需要暂停所有线程。
  2. 并发标记:和用户线程并发执行,标记出所有可达对象。
  3. 重新标记:修正并发标记期间因用户线程操作导致标记变动的情况,需要暂停所有用户线程。
  4. 并发清除:与用户线程并发执行,清除未被标记的对象。
  • 优点:与用户线程并发执行,减少停顿时间。
  • 缺点:基于“标记-清除”算法,收集结束时可能会产生大量空间碎片;对CPU资源敏感;无法处理浮动垃圾。
  1. G1收集器
  • 工作原理:G1收集器是一种面向服务器的垃圾收集器,基于“标记-整理”和“复制”算法实现。他将堆空间划分为多个大小相等的独立区域,并优先收集垃圾最多的区域。
  • 优点:适用于高吞吐量的应用程序,在多个处理器之间并行的进行操作,提高处理效率。
  • 缺点:启动时间长,需要对整个堆空间进行分区,启动时间较长。需要额外的内存来存储标记信息和回收状态信息。

6. 垃圾回收算法的实现原理

  • 标记-清除算法:首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象。
  • 标记-整理算法:标记过程和上述标记-清除算法一样,但后续步骤不是直接对可回收对象进行清理的,而是让所有存活的对象都向一端移动,然后直接清理掉边界外的内存。
  • 复制算法:将可用内存按容量分为两块,每次只使用其中一块,当这一块内存用完后,将还活着的对象复制到另一块上面。然后再把已使用过的空间一次清理掉。

7. 当出现内存溢出,怎么排查错误

  • 首先控制台查看错误日志。
  • 使用jmap查看堆转储快照。
  • 定位出内存溢出的空间:堆、栈、还是永久代。
  • 如果是堆内存溢出,看是否创建了超大的对象。
  • 如果是栈内存溢出,看是否创建了超大的对象或者产生了方法调用的死循环。

8. JVM内存模型相关,重排序、内存屏障、happen-before、主内存、工作内存等。

重排序:

  • 重排序指编译器和处理器为了优化程序性能而对指令序列进行重新排序的一种手段。

内存屏障

  • 内存屏障可以确保某些操作按照预定的顺序执行,防止编译器和处理器对指令进行重排序;内存屏障可以确保写入一个共享变量的操作在后续的读操作前对其他线程可见。

Happen-Before原则

  • 指一个操作的结果对另一个操作是可见的,即一个操作的结果可以被后续操作获取或感知到。这个原则保证了跨线程的内存可见性。

主内存

  • 所有线程共享的内存空间。

工作内存

  • 工作内存指每个线程特有的内存空间,工作内存中保存了被该线程使用到的变量的主内存副本拷贝,线程对变量的所有操作(读取、赋值)都必须在工作内存中进行,而不能直接读写在主内存中的变量。

9. Java的反射机制

他允许程序在运行时查询和使用任何类的信息,包括类的成员变量、方法、构造函数等。这种机制主要通过java.lang.reflect包中的类和接口实现。

10. G1和CMS区别,吞吐量优先和响应优先的垃圾收集器选择

  • CMS是基于“标记-清除”实现的,主要步骤是初始标记、并行标记、重新标记、并发清除。
  • G1是基于“标记-整理”实现的,主要步骤是初始标记、并发标记、最终标记和筛选回收。

CMS的缺点是对CPU要求比较高。
G1的缺点是将内存划分成很多块,所以对内存段的大小有很大的要求。
CMS是清除,所以有很多内存碎片。
G1是整理,所以碎片空间很小。
CMS和G1都是响应优先,他们的目的都是尽量控制STW时间。
G1和CMS的Full Gc都是单线程的mark sweep compact算法,直到JDK10才优化成并行的。
CMS目前只用于老年代,G1将整个Java堆划分为多个大小不等的独立区域,虽然还保留有老年代和新生代的概念,但是不在物理隔开,他们都是Region的集合。

吞吐量优先选择Parallel Scavenge收集器。

11. 解释如下JVM参数含义

  • -server 服务器模式
  • -Xms512m:初始堆内存大小
  • -Xmx512m: 最大堆内存大小
  • -Xss1024k: 栈大小
  • -XX:PermSize=256m:初始永久代大小
  • -XX:MaxPermSize=512m:最大永久代大小
  • -XX:MaxTenuringThreshold=20:新生对象存活次数为20时,晋升到老年代
  • -XX:CMSInitiatingOccupancyFraction=80 :CMS在对老年代内存占用率达到80%时,开始GC
  • -XX:+UseCMSInitiatingOccupancyOnly : 只使用设定的阈值(如上80%),如果不指定,JVM仅在第一次GC时使用设定值,后续则自动调整。

12. 运行时数据中哪些区域是线程共享的,哪些是独享的

JVM内存区域中,程序计数器、虚拟机栈、本地方法栈是线程独享的。
堆、方法区是线程共享的,但是,值得注意的是,Java堆其实还为每一个线程单独分配一个TLAB(本地线程分配缓冲)。
创建对象时,内存分配过程是如何保证线程安全性?有两种解决方案:

  • 对分配内存空间的动作进行同步处理,例如CAS机制,配合失败重试的方式更新操作的线程安全性。
  • 每个线程在Java堆中预先分配一小块内存即线程本地分配缓冲(TLAB),然后再给对象分配内存时,在自己的分配缓冲上进行分配,当这部分空间用完后,在分配新的“私有”内存。

13. 什么是TLAB

TLAB(线程本地分配缓冲区)是Java虚拟机中的一种内存分配优化技术,特别是在使用垃圾收集器时非常常见,TLAB的目的是减少多线程环境下对象分配时的线程同步开销,提高内存分配效率。
工作原理:

  • 在多线程环境下,多个线程可能会同时尝试在堆上分配内存,如果不采取任何措施,这些线程可能会因为竞争同一个内存分配点而陷入等待。这不仅会降低程序性能,还可能引发线程饥饿。为了解决这个问题,JVM引入了TLAB,每个线程在分配内存时,都会尝试在TLAB中分配,TLAB是一块从堆中预先分配给线程的私有内存区域。如果TLAB中有足够的空间,线程就可以直接在其中分配内存,而无需进行任何同步操作,只有当TLAB耗尽时,线程才会尝试从堆中分配更多的内存来填充TLAB,这时可能需要进行同步操作。

14. Java中的数组是存储在堆上还是栈上

在Java中,数组同样是一个对象,所以对象在内存中如何存放同样适用于数组,所以,数组的实例是保存在堆中,而数组的引用是保存在栈上的。

15. Java对象创建的过程是怎样的

  1. 当虚拟机遇到new指令,到常量池定位到这个类的符号引用。
  2. 检查符号引用代表的类是否被加载、解析、初始化过,如果没有的话,执行类加载过程。
  3. 虚拟机为对象分配内存,根据Java内存是否规整,分别通过“指针碰撞”和“空闲列表”来分配。
  4. 虚拟机将分配到的内存空间都初始化为零值。
  5. 虚拟机对对象进行必要的设置。
  6. 执行方法、成员变量进行初始化。

16. 类加载过程

Java 虚拟机类加载过程分为加载、验证、准备、解析和初始化5个阶段。类加载过程

17. 在Java中,可以作为GC Roots的对象有什么

  • 虚拟机栈中引用的对象
  • 方法区中类静态属性引用的对象
  • 方法区中常量引用的对象
  • 本地方法栈中引用的对象。

18. JDK1.8 虚拟机内存模型变化

在JDK1.8中最大的变化是取消了永久区Perm,而是用元数据空间MetaSpace来进行替换,元空间占用的内存不是虚拟机内部的,而是本地内存空间,使用本地内存空间,类的元数据等不再受到永久代大小限制,而是和系统可用内存空间一致。

19. 频繁GC的原因

  • 频繁调用System.gc()
  • 设置的堆大小比较小,可以提高堆的空间。
  • 构建对象非常频繁,并且有很多大对象。

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

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

相关文章

剪映怎么剪辑视频?2024年视频剪辑新手必读指南!

在快节奏的工作里,掌握快速剪辑视频的技巧真的很有用。不管是要做个产品展示、录制培训材料,还是制作社交媒体上的内容,有一款好用的视频剪辑软件,工作效率立马提升好几个档次。咱们今天就先来聊聊剪映怎么剪辑视频?如…

如果忘了Linux密码如何重置?

忘记密码是我们常会遇到的情况之一,无论是在操作系统、网站账户、手机、电子邮件还是其他渠道上。 忘记密码是我们常会遇到的情况之一,无论是在操作系统、网站账户、手机、电子邮件还是其他渠道上。有时候如果密码需要符合特定的复杂性要求,…

哈佛大学单细胞课程|笔记汇总 (三)

哈佛大学单细胞课程|笔记汇总 (一) 哈佛大学单细胞课程|笔记汇总 (二) 听哈佛大神讲怎么做单细胞转录组GSEA分析 (三)Single-cell RNA-seq: Quality control set-up 在生成count矩阵后,我们需…

基于大数据的混合音乐推荐系统的设计与设计(论文+源码)_kaic

摘 要 随着数据的不断增长和用户对随听随播的收听方式的习惯,开发一款音乐推荐系统变得越来越必要。为了满足这一需求,本论文采用Java语言、Vue以及数据库MySQL进行开发。系统的主要功能包括登录注册、音乐分类管理、音乐推荐管理、音乐资讯管理、音乐库…

PCIe学习笔记(16)

层次结构(Hierarchy)ID Message (PCIe I/O 互连的树形拓扑结构称为 PCIe 的 Hierarchy,或称层级、层次(不是事务层、数据链路层的“层”)。层次区域是指与 RC 某一 RP 相关联的所有设备和链路组成的线路结…

微服务之SpringAMQP详解

目录 前言 1. 概述 2. Basic Queue简单队列模型 2.1 消息发送 2.2 消息接收 2.3 总结 3. WorkQueue模型 3.1 消息发送 3.2 消息接收 3.3 测试 3.4 消费预取限制 3.5 总结 4. 发布、订阅 5. Fanout 5.1 声明队列和交换机 5.2 消息发送 5.3 消息接收 5.4 测试 5…

Linux常用命令学习

常用apt命令. apt(Advanced Packaging Tool)是一个在 Debian 和 Ubuntu 中的 Shell 前端软件包管理器。 apt 命令提供了查找、安装、升级、删除某一个、一组甚至全部软件包的命令,而且命令简洁而又好记。 apt 命令执行需要超级管理员权限(ro…

【Java】Java泛型、集合、UML统一建模语言、final关键字

昨天在昆仑巢,下午练习Spring Boot的过滤器Filter。 昨天傍晚开始阅读《疯狂Java讲义(第2版)》,熟悉了UML建模语言、Final修饰符、List集合和泛型。 1.UML建模语言: 13种图,常用的包括用例图、类图、组件图、部署图、顺序图、活动图和状态机…

JVM结构、架构与生命周期总结

【1】JVM结构 不同厂商的JVM产品 : 厂商JVMOracle-SUNHotspotOracleJRocketIBMJ9 JVM阿里Taobao JVM HotSpot VM是目前市面上高性能虚拟机的代表作之一。它采用解释器与即时编译器并存的架构。 在今天,Java程序的运行性能早已脱胎换骨,已…

文章管理接口——里面有动态SQL编写,在分页查询里

1.实体类和表结构 2. 新增文章分类 接口文档 实现 完整代码放在校验部分 结果: 参数校验(Validation自定义) 对state的校验(已发布|草稿),已有的注解不能满足校验需求,这时就需要自定义校验注解…

[Bugku] web-CTF靶场系列系列详解④!!!

平台为“山东安信安全技术有限公司”自研CTF/AWD一体化平台,部分赛题采用动态FLAG形式,避免直接抄袭答案。 平台有题库、赛事预告、工具库、Writeup库等模块。 --------------------------------- eval 开启环境: 进入页面发现是一道php题&…

如何用 ChatGPT 提升学术写作:15 个高效提示

在本文,我们详细探讨了如何利用 ChatGPT 提升学术写作的各个方面。我们帮助学术作者通过生成创意点子、构建论证结构、克服写作障碍以及格式化引用,从而显著提升其学术论文的质量。这 15 条提示不仅可以单独使用,还可作为学习的良好范例。 本…

集合基础知识及练习

import java.util.ArrayList;public class Solution {//将字符串转化为整数public static void main(String[] args) {ArrayList<String> listnew ArrayList();list.add("aaa");list.add("aaa");list.add("bbb");list.add("ccc"…

Occlusion in Augmented Reality

1.Occlusion in Augmented Reality 笔记来源&#xff1a; 1.Occlusion handling in Augmented Reality context 2.Occlusion in Augmented Reality 3.Real-Time Occlusion Handling in Augmented Reality Based on an Object Tracking Approach 4.Occlusion Matting: Realisti…

JavaWeb——CSS的使用

CSS 层叠样式表(英文全称:(cascading stle sheets)能够对网页中元素位置的排版进行像素级精确控制&#xff0c;支持几乎所有的字体字号样式&#xff0c;拥有对网页对象和模型样式编辑的能力,简单来说,CSS用来美化页面 一、CSS的引入方式: 1.行内式&#xff1a;通过元素开始标…

未授权访问漏洞系列

环境 1.此漏洞需要靶场vulhub&#xff0c;可自行前往gethub下载 2.需要虚拟机或云服务器等linux系统&#xff0c;并在此系统安装docker和docker-compose提供环境支持 3.运行docker-compose指令为docker-compose up -d即可运行当前目录下的文件 Redis未授权访问漏洞 一、进…

用于相位解包的卷积和空间四向 LSTM 联合网络

原文&#xff1a;A Joint Convolutional and Spatial Quad-Directional LSTM Network for Phase Unwrapping 作者&#xff1a;Malsha V. Perera 和 Ashwin De Silva 摘要&#xff1a; 相位展开是一个经典的病态问题&#xff0c;其目标是从包裹相位中恢复真实的相位。本文&…

RAG前沿技术/解决方案梳理

RAG前沿技术/解决方案梳理 BenchmarkRetrievalAdaptive-RAGDR-RAGRichRAGGenRT Critique/ReasoningSelf-RAGCorrective RAGSpeculative RAGPlanRAGSelf-ReasoningReSP MemorySelfmemHippoRAG Query RewriteRaFe SummaryRefiner 个人理解 对当前RAG的学术研究&#xff08;或者好…

SAP 接口PO(PI,XI)在ECC端日志记录及显示

在接口的处理中通常会需要记录日志&#xff0c;而如果是与PO(PI,XI)做的接口的话&#xff0c;可以使用事务码SXI_MONITOR – XI&#xff1a;消息监控&#xff0c;来查询日志&#xff0c;但对于一些有加密&#xff0c;或者在业务接口功能上想直接查询报文日志时&#xff0c;会在…

使用 MinIO、Langchain 和 Ray Data 构建分布式嵌入式子系统

嵌入子系统是实现检索增强生成所需的四个子系统之一。它将您的自定义语料库转换为可以搜索语义含义的向量数据库。其他子系统是用于创建自定义语料库的数据管道&#xff0c;用于查询向量数据库以向用户查询添加更多上下文的检索器&#xff0c;最后是托管大型语言模型 &#xff…