Java虚拟机面试题:内存管理(下)
🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/?__c=1000,移动端可微信小程序搜索“历代文学”)总架构师,
15年工作经验,精通Java编程,高并发设计,Springboot和微服务,熟悉Linux,ESXI虚拟化以及云原生Docker和K8s,热衷于探索科技的边界,并将理论知识转化为实际应用。保持对新技术的好奇心,乐于分享所学,希望通过我的实践经历和见解,启发他人的创新思维。在这里,我希望能与志同道合的朋友交流探讨,共同进步,一起在技术的世界里不断学习成长。
技术合作请加本人wx(注明来自csdn):foreast_sea


1. 对象一定分配在堆中吗?有没有了解逃逸分析技术?
在 Java 中,并不是所有对象都严格在堆上分配内存,虽然堆(Heap)是 Java 对象内存分配的主要区域。
在某些情况下,JVM 的即时编译器(JIT)可能会将对象分配在栈上,这被称为逃逸分析(Escape Analysis)。
也就是说,如果编译器确定一个对象不会在方法外部使用(即对象不会逃逸出方法的作用域),那么该对象可以分配在栈上,而不是堆上。
什么是逃逸分析?
逃逸分析是指分析指针动态范围的方法,它同编译器优化原理的指针分析和外形分析相关联。当变量(或者对象)在方法中分配后,其指针有可能被返回或者被全局引用,这样就会被其他方法或者线程所引用,这种现象称作指针(或者引用)的逃逸(Escape)。
通俗点讲,当一个对象被 new 出来之后,它可能被外部所调用,如果是作为参数传递到外部了,就称之为方法逃逸。

除此之外,如果对象还有可能被外部线程访问到,例如赋值给可以在其它线程中访问的实例变量,这种就被称为线程逃逸。

逃逸分析有什么好处?
- 栈上分配
如果确定一个对象不会逃逸到线程之外,那么久可以考虑将这个对象在栈上分配,对象占用的内存随着栈帧出栈而销毁,这样一来,垃圾收集的压力就降低很多。
- 同步消除
线程同步本身是一个相对耗时的过程,如果逃逸分析能够确定一个变量不会逃逸出线程,无法被其他线程访问,那么这个变量的读写肯定就不会有竞争, 对这个变量实施的同步措施也就可以安全地消除掉。
- 标量替换
如果一个数据是基本数据类型,不可拆分,它就被称之为标量。把一个 Java 对象拆散,将其用到的成员变量恢复为原始类型来访问,这个过程就称为标量替换。假如逃逸分析能够证明一个对象不会被方法外部访问,并且这个对象可以被拆散,那么可以不创建对象,直接用创建若干个成员变量代替,可以让对象的成员变量在栈上分配和读写。
2. 内存溢出和内存泄漏是什么意思?
内存溢出,俗称 OOM,是指当程序请求分配内存时,由于没有足够的内存空间满足其需求,从而触发的错误。在 Java 中,这种情况会抛出 OutOfMemoryError。
内存溢出可能是由于内存泄漏导致的,也可能是因为程序一次性尝试分配大量内存,内存直接就干崩溃了导致的。
内存泄漏是指程序在使用完内存后,未能释放已分配的内存空间,导致这部分内存无法再被使用。随着时间的推移,内存泄漏会导致可用内存逐渐减少,最终可能导致内存溢出。
在 Java 中,内存泄漏通常发生在长期存活的对象持有短期存活对象的引用,而长期存活的对象又没有及时释放对短期存活对象的引用,从而导致短期存活对象无法被回收。
用一个比较有味道的比喻来形容就是,内存溢出是排队去蹲坑,发现没坑了;内存泄漏,就是有人占着茅坑不拉屎,占着茅坑不拉屎的多了可能会导致坑位不够用。

3. 能手写内存溢出的例子吗?
导致内存溢出(OOM)的原因有很多,比如一次性创建了大量对象导致堆内存溢出;比如说元空间溢出,抛出 java.lang.OutOfMemoryError:Metaspace,比如说栈溢出,如果栈的深度超过了 JVM 栈所允许的深度,将会抛出 StackOverflowError。
堆内存溢出是最常见的 OOM 原因,通常是因为创建了大量的对象,且长时间无法被垃圾收集器回收,导致堆内存耗尽。
这就相当于一个房子里,不断堆积不能被回收的杂物,那么房子很快就会被堆满了。
来通过代码模拟一下堆内存溢出的情况。
public class HeapSpaceErrorGenerator {public static void main(String[] args) {List<byte[]> bigObjects = new ArrayList<>();try {while (true) {// 创建一个大约 10MB 的数组byte[] bigObject = new byte[10 * 1024 * 1024];bigObjects.add(bigObject);}} catch (OutOfMemoryError e) {System.out.println("OutOfMemoryError 发生在 " + bigObjects.size() + " 对象后");throw e;}}
}
通过 VM 参数设置堆内存大小为 -Xmx128M,然后运行程序。

可以看到,堆内存溢出发生在 11 个对象后。

4. 内存泄漏可能由哪些原因导致呢?
比如说:
①、静态的集合中添加的对象越来越多,但却没有及时清理;
public class OOM {static List list = new ArrayList();public void oomTests(){Object obj = new Object();list.add(obj);}
}
②、单例模式下对象持有的外部引用无法及时释放;
③、数据库、IO、Socket 等连接资源没有及时关闭;
try {Connection conn = null;Class.forName("com.mysql.jdbc.Driver");conn = DriverManager.getConnection("url", "", "");Statement stmt = conn.createStatement();ResultSet rs = stmt.executeQuery("....");} catch (Exception e) {}finally {//不关闭连接}
④、变量的作用域不合理;
class Simple {Object object;public void method1(){object = new Object();//...其他代码//由于作用域原因,method1执行完成之后,object 对象所分配的内存不会马上释放}
}
⑤、hash 值发生变化但对象却没有改变,这也是为什么 String 被设计成不可变对象的原因之一,就是因为假如 String 的哈希值发生了改变,但对应的值没变,就导致 HashMap 中的对象无法被及时清理;
⑥、使用完 ThreadLocal 没有使用 remove 方法来进行清除。

5. 有没有处理过内存泄漏问题?是如何定位的?
有,内存泄漏是指程序在运行过程中由于未能正确释放已分配的内存,导致内存无法被重用,从而引发内存耗尽等问题。
当时在做技术派项目的时候,由于 ThreadLocal 没有及时清理导致出现了内存泄漏问题。
常用的可视化监控工具有 JConsole、VisualVM、JProfiler、Eclipse Memory Analyzer (MAT)等。
也可以使用 JDK 自带的 jmap、jstack、jstat 等命令行工具来配合内存泄露问题的排查。
严重的内存泄漏往往伴随频繁的 Full GC,所以排查内存泄漏问题时,可以从 Full GC 入手。
第一步,使用 jps -l 查看运行的 Java 进程 ID。

第二步,使用top -p [pid] 查看进程使用 CPU 和内存占用情况。

第三步,使用 top -Hp [pid] 查看进程下的所有线程占用 CPU 和内存情况。

第四步,抓取线程栈:jstack -F 29452 > 29452.txt,可以多抓几次做个对比。
29452 为 pid,顺带作为文件名。

看看有没有线程死锁、死循环或长时间等待这些问题。

第五步,可以使用jstat -gcutil [pid] 5000 10 每隔 5 秒输出 GC 信息,输出 10 次,查看 YGC 和 Full GC 次数。

通常会出现 YGC 不增加或增加缓慢,而 Full GC 增加很快。
或使用 jstat -gccause [pid] 5000 输出 GC 摘要信息。

或使用 jmap -heap [pid] 查看堆的摘要信息,关注老年代内存使用是否达到阀值,若达到阀值就会执行 Full GC。

如果发现 Full GC 次数太多,就很大概率存在内存泄漏了。
第六步,生成 dump 文件,然后借助可视化工具分析哪个对象非常多,基本就能定位到问题根源了。
执行命令 jmap -dump:format=b,file=heap.hprof 10025 会输出进程 10025 的堆快照信息,保存到文件 heap.hprof 中。

第七步,可以使用图形化工具分析,如 JDK 自带的 VisualVM,从菜单 > 文件 > 装入 dump 文件。

然后在结果观察内存占用最多的对象,找到内存泄漏的源头。
6. 有没有处理过内存溢出问题?
有,内存溢出,也就是 Out of Memory,是指当程序请求分配内存时,由于没有足够的内存空间满足其需求,从而触发的错误。
当时在做技术派的时候,由于上传的文件过大,没有正确处理,导致一下子撑爆了内存,程序直接崩溃了。
当发生 OOM 时,可以导出堆转储(Heap Dump)文件进行分析。如果 JVM 还在运行,可以使用 jmap 命令手动生成 Heap Dump 文件:
jmap -dump:format=b,file=heap.hprof <pid>
生成 Heap Dump 文件后,可以使用 MAT、JProfiler 等工具进行分析,查看内存中的对象占用情况,找到内存泄漏的原因。
如果生产环境的内存还有很多空余,可以适当增大堆内存大小,例如 -Xmx4g 参数。
或者检查代码中是否存在内存泄漏,如未关闭的资源、长生命周期的对象等。
之后,我会在本地进行压力测试,模拟高负载情况下的内存表现,确保修改有效,且没有引入新的问题。
7. 什么情况下会发生栈溢出?(补充)
栈溢出(StackOverflowError)发生在程序调用栈的深度超过 JVM 允许的最大深度时。栈溢出的本质是因为线程的栈空间不足,导致无法再为新的栈帧分配内存。

当一个方法被调用时,JVM 会在栈中分配一个栈帧,用于存储该方法的执行信息。如果方法调用嵌套太深,栈帧不断压入栈中,最终会导致栈空间耗尽,抛出 StackOverflowError。
最常见的栈溢出场景是递归调用,尤其是没有正确的终止条件,导致递归无限进行。
class StackOverflowExample {public static void recursiveMethod() {// 没有终止条件的递归调用recursiveMethod();}public static void main(String[] args) {recursiveMethod(); // 导致栈溢出}
}
另外,如果方法中定义了特别大的局部变量,栈帧会变得很大,导致栈空间更容易耗尽。
public class LargeLocalVariables {public static void method() {int[] largeArray = new int[1000000]; // 大量局部变量method(); // 递归调用}public static void main(String[] args) {method(); // 导致栈溢出}
}
相关文章:
Java虚拟机面试题:内存管理(下)
🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/?__c1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,精通Java编…...
R语言用逻辑回归贝叶斯层次对本垒打数据与心脏移植数据后验预测检验模拟推断及先验影响分析|附数据代码...
全文链接:https://tecdat.cn/?p40152 在统计学领域中,层次建模是一种极为强大且实用的工具。它能够巧妙地处理复杂的数据结构,通过分层的方式对数据进行建模。在贝叶斯统计的框架内,层次建模优势尽显,其可以有效地融合…...
网页制作02-html,css,javascript初认识のhtml的文字与段落标记
用一首李白的将进酒,对文字与段落标记进行一个简单的介绍演示: 目录 一、标题字 1、标题字标记h 2、标题字对其属性align 二、文本基本标记 1、字体属性face 2、字号属性size 3、颜色属性 Color 三、文本格式化标记 1、粗体标记 b ,strong 2、…...
【SpringBoot苍穹外卖】debugDay04
一、getById 与 new 我在修改数据时,产生疑问,注释掉是我一开始写得,new对象是答案提供的,我就好奇两者之间区别。 1. 使用 setmealMapper.getById 获取现有对象 Setmeal setmeal setmealMapper.getById(setmealDTO.getId()); …...
C++中的顺序容器(一)
文章目录 顺序容器概述所有容器类型都支持的操作迭代器容器定义与初始化将一个容器初始化为另一个容器的拷贝标准库array具有固定大小 赋值和swap关系运算符 顺序容器的特有操作向顺序容器添加元素访问元素删除元素特殊的forward_list操作改变容器的大小容器操作可能是迭代器失…...
【复现DeepSeek-R1之Open R1实战】系列4:跑通GRPO!
目录 1 配置环境2 训练2.1 命令和配置参数2.2 num_generations2.2.1 参数定义2.2.2 参数含义2.2.3 示例2.2.4 使用场景2.2.5 示例代码 2.3 显存占用和耗时 3 结果 1 配置环境 关于环境配置,可以参考这篇博文:【复现DeepSeek-R1之Open R1实战】系列1&…...
Redis原理简述及发布订阅消息队列
目录 1 什么是Redis 2 Redis 非阻塞IO内部原理 2.1 IO多路复用策略 2.2 Reactor设计模式 3 基于PubSub的消息队列(发布-订阅) 由于集群之后存在多台服务器,并且不同客户端连接的可能是不同的服务器,因此在聊天过程中涉及到服…...
ThreadLocal为什么会内存溢出
每个线程(Thread 对象)内部维护一个 ThreadLocalMap,用于存储该线程的所有 ThreadLocal 变量的键值对: ThreadLocalMap虽然是ThreadLocal的静态内部类,但是Thread 对象的属性,当线程存活时ThreadLocalMap不会被回收。 Key:ThreadLocal 实例的 弱引用(WeakReference)。…...
假面与演员:到底是接口在使用类,还是类在使用接口?编程接口与物理接口的区别又是什么?
前言:本篇文章解释了接口学习过程中的2个常见问题,一个是“为什么是类在使用接口”,另一个一个是“编程接口与物理接口的差异源于所处的抽象层次和交互模式的不同”,旨在揭示编程接口的本质。 Part1.是类在使用接口 当学习接口时…...
数据结构——Makefile、算法、排序(2025.2.13)
目录 一、Makefile 1.功能 2.基本语法和相关操作 (1)创建Makefile文件 (2)编译规则 (3)编译 (4)变量 ①系统变量 ②自定义变量 二、 算法 1.定义 2.算法的设计 ÿ…...
算法之 跳跃游戏
文章目录 55.跳跃游戏思路参考:56.合并区间 55.跳跃游戏 55.跳跃游戏 灵神思路 思路分析: 两种思路,思路1是我们可以直接维护当前到达i的时候所能到达的最右的边界mr,如果i>mr就说明无法到达i,否则就是可以到达;…...
C#中的图形渲染模式
在C#中,图形模式通常用于定义如何渲染或处理图形。可以枚举定义如下四种图形模式:AUTO、GDI、DIB 和 FBO。这些模式可能用于指定不同的图形渲染技术或后端。下面是对这些模式的详细解释: 1. AUTO (自动模式) 含义:自动选择最适合…...
二.数据治理流程架构
1、数据治理流程架构核心思想: 该图描绘了一个以数据标准规范体系为核心,大数据生命周期管理为主线,数据资源中心为依托,并辅以数据质量管理和大数据安全与隐私管理的数据治理流程架构。它旨在通过规范化的流程和技术手段&#x…...
瑞萨RA-T系列芯片ADCGPT功能模块的配合使用
在马达或电源工程中,往往需要采集多路AD信号,且这些信号的优先级和采样时机不相同。本篇介绍在使用RA-T系列芯片建立马达或电源工程时,如何根据需求来设置主要功能模块ADC&GPT,包括采样通道打包和分组,GPT触发启动…...
扩散模型中的马尔可夫链设计演进:从DDPM到Stable Diffusion全解析
一、技术原理与数学推导(附核心公式) 1.1 扩散过程数学建模 马尔可夫链前向过程定义: q(x_{1:T}|x_0) \prod_{t1}^T q(x_t|x_{t-1})噪声调度函数(以余弦调度为例): \beta_t \frac{1 - \cos(\pi t/T)}…...
通俗诠释 DeepSeek-V3 模型的 “671B” ,“37B”与 “128K”,用生活比喻帮你理解模型的秘密!
欢迎来到涛涛聊AI。 在DeepSeek-V3模型的参数描述中,你可能会看到类似“671B 37B 128K”这样的标记。这些字母和数字的组合看起来像密码,但其实它们揭示了模型的“大脑容量”和“工作方式”。我们用日常生活的比喻来解释: 一、数字含义&…...
大模型常识:什么是大模型/大语言模型/LLM
本文原创作者:姚瑞南 AI-agent 大模型运营专家,先后任职于美团、猎聘等中大厂AI训练专家和智能运营专家岗;多年人工智能行业智能产品运营及大模型落地经验,拥有AI外呼方向国家专利与PMP项目管理证书。(转载需经授权) 目录 一、什么是语言模型? 那么什么是语言模…...
iOS 中使用 FFmpeg 进行音视频处理
在 iOS 中使用 FFmpeg 进行音视频处理,通常需要将 FFmpeg 的功能集成到项目中。由于 FFmpeg 是一个 C 库,直接在 iOS 中使用需要进行一些配置和封装。 1. 在 iOS 项目中集成 FFmpeg 方法 1:使用 FFmpeg 预编译库 下载 FFmpeg iOS 预编译库: 可以从以下项目中获取预编译的 …...
SAP-ABAP:SAP的Screen Layout Designer屏幕布局设计器详解及示例
在SAP中,Screen Layout Designer(屏幕布局设计器)是用于设计和维护屏幕(Dynpro)布局的工具。通过Screen Layout Designer,您可以创建和修改屏幕元素(如输入字段、按钮、文本、表格控件等&#x…...
一.数据治理理论架构
1、数据治理核心思想: 数据治理理论架构图描绘了一个由顶层设计、管控机制、核心领域和管理系统四个主要部分组成的数据治理框架。它旨在通过系统化的方法,解决数据治理机制缺失引发的业务和技术问题,并最终提升企业的数据管理水平。 数据治…...
ElasticSearch搜索引擎之倒排索引及其底层算法
文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...
Ascend NPU上适配Step-Audio模型
1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统,支持多语言对话(如 中文,英文,日语),语音情感(如 开心,悲伤)&#x…...
ABAP设计模式之---“简单设计原则(Simple Design)”
“Simple Design”(简单设计)是软件开发中的一个重要理念,倡导以最简单的方式实现软件功能,以确保代码清晰易懂、易维护,并在项目需求变化时能够快速适应。 其核心目标是避免复杂和过度设计,遵循“让事情保…...
JS设计模式(4):观察者模式
JS设计模式(4):观察者模式 一、引入 在开发中,我们经常会遇到这样的场景:一个对象的状态变化需要自动通知其他对象,比如: 电商平台中,商品库存变化时需要通知所有订阅该商品的用户;新闻网站中࿰…...
基于 TAPD 进行项目管理
起因 自己写了个小工具,仓库用的Github。之前在用markdown进行需求管理,现在随着功能的增加,感觉有点难以管理了,所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD,需要提供一个企业名新建一个项目&#…...
莫兰迪高级灰总结计划简约商务通用PPT模版
莫兰迪高级灰总结计划简约商务通用PPT模版,莫兰迪调色板清新简约工作汇报PPT模版,莫兰迪时尚风极简设计PPT模版,大学生毕业论文答辩PPT模版,莫兰迪配色总结计划简约商务通用PPT模版,莫兰迪商务汇报PPT模版,…...
打手机检测算法AI智能分析网关V4守护公共/工业/医疗等多场景安全应用
一、方案背景 在现代生产与生活场景中,如工厂高危作业区、医院手术室、公共场景等,人员违规打手机的行为潜藏着巨大风险。传统依靠人工巡查的监管方式,存在效率低、覆盖面不足、判断主观性强等问题,难以满足对人员打手机行为精…...
上位机开发过程中的设计模式体会(1):工厂方法模式、单例模式和生成器模式
简介 在我的 QT/C 开发工作中,合理运用设计模式极大地提高了代码的可维护性和可扩展性。本文将分享我在实际项目中应用的三种创造型模式:工厂方法模式、单例模式和生成器模式。 1. 工厂模式 (Factory Pattern) 应用场景 在我的 QT 项目中曾经有一个需…...
Modbus RTU与Modbus TCP详解指南
目录 1. Modbus协议基础 1.1 什么是Modbus? 1.2 Modbus协议历史 1.3 Modbus协议族 1.4 Modbus通信模型 🎭 主从架构 🔄 请求响应模式 2. Modbus RTU详解 2.1 RTU是什么? 2.2 RTU物理层 🔌 连接方式 ⚡ 通信参数 2.3 RTU数据帧格式 📦 帧结构详解 🔍…...
基于江科大stm32屏幕驱动,实现OLED多级菜单(动画效果),结构体链表实现(独创源码)
引言 在嵌入式系统中,用户界面的设计往往直接影响到用户体验。本文将以STM32微控制器和OLED显示屏为例,介绍如何实现一个多级菜单系统。该系统支持用户通过按键导航菜单,执行相应操作,并提供平滑的滚动动画效果。 本文设计了一个…...
