Java中的内存泄露、内存溢出与栈溢出
内存泄露、内存溢出与栈溢出
- 1、概述
- 2、内存泄漏、内存溢出和栈溢出
- 2.1、内存泄漏
- 2.2、内存溢出
- 2.3、栈溢出
- 2、总结
1、概述
大家好,我是欧阳方超。本次就Java中几个相似而又不同的概念做一下介绍。内存泄漏、内存溢出和栈溢出都是与内存相关的问题,但它们之间有所不同。
2、内存泄漏、内存溢出和栈溢出
我们经常会遇到内存泄漏、内存溢出和栈溢出等问题,这些问题都与内存的使用有关。
2.1、内存泄漏
内存泄漏(memory leak)指的是程序在使用内存时,未将不再使用的内存释放,导致内存不断占用而无法再次使用。内存泄漏的原因可能是程序中存在未释放的资源、对象引用未被清理、内存分配过多等。当程序中存在大量的内存泄漏时,可能会导致系统性能下降、程序崩溃等问题。
解决方法:及时释放不再使用的资源、对象引用,避免内存分配过多,使用内存检测工具进行检测和修复。
2.2、内存溢出
内存溢出(out of memory)指的是程序在运行时,申请的内存空间超过了系统可用的内存空间。内存溢出的原因可能是程序中存在大量的内存泄漏、对象过多、内存分配过多等。当程序中出现内存溢出时,可能会导致程序崩溃、系统异常等问题。
解决方法:及时释放不再使用的资源、对象引用,避免内存分配过多,使用内存检测工具进行检测和修复,增加系统内存等。
注意,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,如果内存泄漏持续发生而又得不到控制的话,无论多少内存,迟早会被耗尽。memory leak会最终会导致out of memory!
既然内存泄漏与内存溢出有关系,我们就用一个例子来验证一下“内存泄漏会导致内存溢出”这一现象,
import java.util.ArrayList;public class Test {public static void main(String[] args) {ArrayList<Integer> integerArrayList = new ArrayList<>();long i = 1;while (true) {integerArrayList.add(1);System.out.println(i + "times");i++;}}
}
在上面的示例代码中,我们创建了一个包含整数的列表,并在一个无限循环中不断向其中添加整数。由于没有终止循环的条件,程序将不断向列表中添加整数,直到内存溢出为止。当内存不再足够容纳更多的整数时,程序将崩溃,并且会抛出一个OutOfMemoryError异常。将上面的程序运行起来,很快就会发生内存溢出的错误(循环进行了70091070次后发生了内存溢出):
70091068times
70091069times
70091070times
Exception in thread "main" java.lang.OutOfMemoryError: Java heap spaceat java.util.Arrays.copyOf(Arrays.java:3210)at java.util.Arrays.copyOf(Arrays.java:3181)at java.util.ArrayList.grow(ArrayList.java:261)at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:235)at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:227)at java.util.ArrayList.add(ArrayList.java:458)
2.3、栈溢出
栈溢出指的是程序在执行过程中,栈空间超过了系统所能支持的范围。栈溢出的原因可能是程序中存在过多的递归调用、方法嵌套过深等。当程序中出现栈溢出时,可能会导致程序崩溃、系统异常等问题。
解决方法:优化递归算法,减少方法的嵌套层数,增加系统栈空间等。
下面是一个使用递归计算阶乘的例子:
public class Test {public static void main(String[] args) {int num = 10; // 需要计算的阶乘long factorial = calcFactorial(num); // 调用递归函数计算阶乘System.out.println(num + "的阶乘是:" + factorial);}public static long calcFactorial(int n) {if (n == 1) { // 递归结束条件return 1;} else {return n * calcFactorial(n - 1); // 递归调用计算阶乘}}
}
在上述代码中,我们定义了一个静态方法calcFactorial,用于递归计算阶乘。如果n等于1,说明阶乘已经计算完成,直接返回1;否则,递归调用calcFactorial(n - 1)计算n - 1的阶乘,然后将结果乘以n,得到n的阶乘。最终,我们在main方法中调用calcFactorial方法计算阶乘,并输出计算结果。
需要注意的是,递归计算阶乘的方法在计算大数阶乘时可能会超出栈的深度限制,导致栈溢出异常。比如我们将上面程序中num的值改为一万,再次运行时立马会发生栈溢出的问题:
Exception in thread "main" java.lang.StackOverflowErrorat Test.calcFactorial(Test.java:12)at Test.calcFactorial(Test.java:15)at Test.calcFactorial(Test.java:15)at Test.calcFactorial(Test.java:15)
在递归时,栈需要保存函数的调用信息,保存的过多的话会导致栈内存不够用,进而发生栈溢出,我们可以将递归实现的阶乘计算优化成循环实现:
public class Factorial {public static void main(String[] args) {int num = 5; // 需要计算的阶乘long factorial = 1; // 阶乘初始值为1for (int i = 1; i <= num; i++) {factorial *= i; // 计算阶乘}System.out.println(num + "的阶乘是:" + factorial);}
}
在上述代码中,我们定义了一个变量num,表示需要计算的阶乘。然后,我们定义了一个long类型的变量factorial,用于存储阶乘的值,初始值为1。接着,我们使用for循环从1到num,每次将当前的i乘到factorial中,最终得到num的阶乘。最后,我们输出计算结果。
需要注意的是,阶乘可能会非常大,超出了long类型的范围,因此在实际应用中需要使用大数类进行计算,以避免计算结果溢出。另外,阶乘的计算也可以使用递归实现,但需要注意递归深度的控制,以避免栈溢出。
2、总结
内存泄漏、内存溢出和栈溢出都是程序中常见的内存问题,它们都会导致程序运行的异常和不稳定。为了避免这些问题,我们需要在编程中注意及时释放不再使用的资源和对象引用,避免内存分配过多,优化算法和代码结构等。同时,我们还可以使用内存检测工具进行检测和修复,在程序开发和测试过程中,及时发现和解决问题,保证程序运行的稳定性和可靠性。
我是欧阳方超,把事情做好了自然就有兴趣了,如果你喜欢我的文章,欢迎点赞、转发、评论加关注。我们下次见。
相关文章:
Java中的内存泄露、内存溢出与栈溢出
内存泄露、内存溢出与栈溢出 1、概述2、内存泄漏、内存溢出和栈溢出2.1、内存泄漏2.2、内存溢出2.3、栈溢出 2、总结 1、概述 大家好,我是欧阳方超。本次就Java中几个相似而又不同的概念做一下介绍。内存泄漏、内存溢出和栈溢出都是与内存相关的问题,但…...
时序预测 | Matlab实现SSA-GRU、GRU麻雀算法优化门控循环单元时间序列预测(含优化前后对比)
时序预测 | Matlab实现SSA-GRU、GRU麻雀算法优化门控循环单元时间序列预测(含优化前后对比) 目录 时序预测 | Matlab实现SSA-GRU、GRU麻雀算法优化门控循环单元时间序列预测(含优化前后对比)预测效果基本介绍程序设计参考资料 预测效果 基本介绍 Matlab实现SSA-GRU、GRU麻雀算法…...
Java+springboot开发的医院HIS信息管理系统实现,系统部署于云端,支持多租户SaaS模式
一、项目技术框架 前端:AngularNginx 后台:JavaSpring,SpringBoot,SpringMVC,SpringSecurity,MyBatisPlus,等 数据库:MySQL MyCat 缓存:RedisJ2Cache 消息队列&…...
【前端面经】Vue-Vue中的 $nextTick 有什么作用?
Vue.js 是一个流行的 JavaScript 框架,它提供了许多实用的功能,其中之一就是 $nextTick 方法。 在 Vue.js 中, $nextTick 方法可以确保我们在更新 DOM 之后再去执行某些操作,从而避免由于 DOM 更新而导致的问题。这个方法非常实用…...
基于STATCOM的风力发电机稳定性问题仿真分析(Simulink)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...
如何写出高质量的代码
背景说明: 你是否曾经为自己写的代码而感到懊恼?你是否想过如何才能写出高质量代码?那就不要错过这个话题!在这里,我们可以讨论什么是高质量代码,如何写出高质量代码等问题。无论你是初学者还是资深开发人…...
15.基于主从博弈的智能小区代理商定价策略及电动汽车充电管理
说明书 MATLAB代码:基于主从博弈的智能小区代理商定价策略及电动汽车充电管理 关键词:电动汽车 主从博弈 动态定价 智能小区 充放电优化 参考文档:《基于主从博弈的智能小区代理商定价策略及电动汽车充电管理》基本复现 仿真平台&#…...
ChatGPT实现多语种翻译
语言翻译 多语种翻译是 NLP 领域的经典话题,也是过去很多 AI 研究的热门领域。一般来说,我们认为主流语种的互译一定程度上属于传统 AI 已经能较好完成的任务。比如谷歌翻译所采用的的神经机器翻译(NMT, Neural Machine Translation)技术就一度让世人惊…...
volatile关键字原理的使用介绍和底层原理解析和使用实例
文章目录 volatile关键字原理的使用介绍和底层原理解析和使用实例1. volatile 关键字的作用2. volatile 的底层原理3. volatile 的使用案例4. volatile 的原子性问题5. 如何解决 volatile 的原子性问题6. volatile 的实现原理7. 小结8. volatile的最佳实践9. 案例:使用volatile…...
【软件下载】换新电脑记录下下载的软件时所需地址
1.idea https://www.jetbrains.com/zh-cn/idea/download/other.html 2.oracle官方(下载jdk时找的) https://www.oracle.com/ 3.jdk8 https://www.oracle.com/java/technologies/downloads/ 下拉找到jdk8 切换windows (需要注册个oracle账…...
【10.HTML入门知识-CSS元素定位】
1 标准流(Normal Flow) 默认情况下,元素都是按照normal flow(标准流、常规流、正常流、文档流【document flow】)进行排布 从左到右、从上到下按顺序摆放好 默认情况下,互相之间不存在层叠现象 1.1…...
LeetCode_贪心算法_简单_455.分发饼干
目录 1.题目2.思路3.代码实现(Java) 1.题目 假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。 对每个孩子 i,都有一个胃口值 g[i],这是能让孩子们满足胃口的饼干的…...
HashMap
目录 HashMap是什么? 为什么要使用HashMap? HashMap存储元素原理(put⽅法) 扰动函数 前置知识 异或运算 &运算 为什么使用扰动函数 实验验证扰动函数 常见问题 HashMap的默认长度是多少? HashMap是先扩…...
数据结构初阶 —— 树(堆)
目录 一,堆 堆的概念 向下调整法(数组) 向上调整法(数组) 堆的创建(建堆) 堆的实现 一,堆 堆的概念 如有个关键码的集合K{,,,...…...
一文看懂低代码,5分钟从入门到原理全搞定
全球低代码市场已经走过了近20年,中国低代码市场近5年经历了百花齐放的广泛探索阶段,更旺盛的市场需求逐步在被激发。现在,让我们按下暂停键,看看这些产品给我们呈现了低代码市场一幅怎样的百景图。 低代码平台简介 广义上的低代…...
MetaERP系统主要干什么的,华为自研ERP的路子是否可以效仿?
近日,华为成功研发出自主可控的MetaERP系统,并完成了对旧有ERP系统的替换。该系统采用全栈自主可控技术,基于华为欧拉操作系统、GaussDB等根技术,采用云原生架构、元数据多租架构、实时智能技术等,提高业务效率&#x…...
自动驾驶——离散LQR的黎卡提方程Riccati公式推导与LQR工程化
1.LQR Question Background 之前写过连续系统的黎卡提方程Riccati推导,但是考虑到实际工程落地使用的是离散系统,于是又进行了离散黎卡提方程Riccati的公式推导。 2.Proof of Riccati Equation Formula for Discrete Systems 工程化落地,就…...
28.Mybatis的入门
目录 一、Mybatis的入门。 (1)Mybatis的简介。 (2)Mybatis的快速入门。 (2.1)快速入门。 (2.2)UserMapper.xml文件。 (2.3)sqlMapConfig.xml文件。 …...
Android Jetpack 从使用到源码深耕【ViewModel从实践到原理 】(三)
上文,我们通过简单的ViewModel使用源码入手,对其源码进行阅读,原理进行了简单总结,简单来说,ViewModel是通过Activity的onRetainNonConfigurationInstance 与 getLastNonConfigurationInstance的自动调用,实现了 ViewModel数据的存储和恢复,数据存储在ViewModelStore的m…...
什么性格的人适合报考环境科学类专业?高考选专业
环境科学类专业包括有:环境科学与工程,环境工程,环境科学,环境生态工程,环保设备工程,资源环境科学,水质科学与技术。 环境对于未来是一个极其重要的方向,需要学生具备一定的科学素…...
【杂谈】-递归进化:人工智能的自我改进与监管挑战
递归进化:人工智能的自我改进与监管挑战 文章目录 递归进化:人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管?3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...
边缘计算医疗风险自查APP开发方案
核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...
Java多线程实现之Callable接口深度解析
Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...
ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放
简介 前面两期文章我们介绍了I2S的读取和写入,一个是通过INMP441麦克风模块采集音频,一个是通过PCM5102A模块播放音频,那如果我们将两者结合起来,将麦克风采集到的音频通过PCM5102A播放,是不是就可以做一个扩音器了呢…...
数据链路层的主要功能是什么
数据链路层(OSI模型第2层)的核心功能是在相邻网络节点(如交换机、主机)间提供可靠的数据帧传输服务,主要职责包括: 🔑 核心功能详解: 帧封装与解封装 封装: 将网络层下发…...
Swagger和OpenApi的前世今生
Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章,二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑: 🔄 一、起源与初创期:Swagger的诞生(2010-2014) 核心…...
NPOI操作EXCEL文件 ——CAD C# 二次开发
缺点:dll.版本容易加载错误。CAD加载插件时,没有加载所有类库。插件运行过程中用到某个类库,会从CAD的安装目录找,找不到就报错了。 【方案2】让CAD在加载过程中把类库加载到内存 【方案3】是发现缺少了哪个库,就用插件程序加载进…...
【安全篇】金刚不坏之身:整合 Spring Security + JWT 实现无状态认证与授权
摘要 本文是《Spring Boot 实战派》系列的第四篇。我们将直面所有 Web 应用都无法回避的核心问题:安全。文章将详细阐述认证(Authentication) 与授权(Authorization的核心概念,对比传统 Session-Cookie 与现代 JWT(JS…...
Neko虚拟浏览器远程协作方案:Docker+内网穿透技术部署实践
前言:本文将向开发者介绍一款创新性协作工具——Neko虚拟浏览器。在数字化协作场景中,跨地域的团队常需面对实时共享屏幕、协同编辑文档等需求。通过本指南,你将掌握在Ubuntu系统中使用容器化技术部署该工具的具体方案,并结合内网…...
Qt的学习(一)
1.什么是Qt Qt特指用来进行桌面应用开发(电脑上写的程序)涉及到的一套技术Qt无法开发网页前端,也不能开发移动应用。 客户端开发的重要任务:编写和用户交互的界面。一般来说和用户交互的界面,有两种典型风格&…...
