关于java递归调用内存泄露

Java多线程递归:优化管理漏洞,提升性能 通过合理地管理线程和优化任务划分与合并,我们可以弥补Java多线程递归中的管理漏洞,并提升性能。使用线程池可以重用线程,减少线程的创建和销毁开销。合理地划分和合并任务可以提高并行度,充分利用多核处理器的计算能力。希望本文对你在Java多线程递归编程方面有所帮助。请注意,以上提供的代码示例仅用于演示线程管理和任务划分的思路,并不保证在所有情况下都是最佳实践。在实际开发中,还需要根据具体的需求和场景进行适当的调整和优化。 阅读详情
看两段代码:
import java.util.ArrayList;   
import java.util.List;   
  
public class TailRecursionTest {   
    public static void main(String[] args) {   
        TailRecursionTest t = new TailRecursionTest();   
        for (int i = 0; i < 10000; i++)   
            t.a(0);   
    }
   
  
    public void a(int j) {   
        j++;   
        List list = new ArrayList<Integer>(100000);   
        // 对list进行处理   
    }
   
}

没啥特殊的,仅仅是为了测试,我们将a方法调用10000次,a方法创建一个有100000个元素的list的局部变量。
第二个程序:
import java.util.ArrayList;   
import java.util.List;   
  
public class TailRecursionTest2 {   
    public static void main(String[] args) {   
        TailRecursionTest2 t = new TailRecursionTest2();   
        t.a(0);   
    }
   
  
    public void a(int j) {   
        System.out.println(j);   
        j++;   
        if (j == 10000)   
            return;   
        List list = new ArrayList<Integer>(100000);   
        // 对list进行处理   
        a(j);   
    }
   
}
  

也没啥特殊的,就是将循环换成了递归,a方法做的事情没变。两个都跑一下,程序1顺利结束,程序2出问题了,啥问题?如下:
161  
162  
163  
164  
165  
Exception in thread 
"main" java.lang.OutOfMemoryError: Java heap space   
    at java.util.ArrayList.
<init>(Unknown Source)   
    at TailRecursionTest2.a(TailRecursionTest2.java:
17)   
    at TailRecursionTest2.a(TailRecursionTest2.java:
20)   
    at TailRecursionTest2.a(TailRecursionTest2.java:
20)   
    at TailRecursionTest2.a(TailRecursionTest2.java:
20)   
    at TailRecursionTest2.a(TailRecursionTest2.java:
20) 

我倒,才运行166次了,heap就满了。问题在哪呢?oh,yep,你肯定想到了,是不是重复创建list这个大集合引起的呢?它不是局部变量吗?怎么也会溢出?是的,list是局部变量,在a的方法栈里引用着,指向heap上的大对象,更关键的问题在于,java是没有尾递归优化的,递归方法是不会使用同一个栈帧,每一次递归调用,都将压入新的栈帧,并且这个栈帧上又new了一个list变量,引用着heap上新的一个大集合。随着栈深度的增加, jvm里维持着一条长长的方法调用轨迹以便你能回来,在方法没有返回之前,这些list变量一直被各自的栈帧引用着,不能被GC,你说,能不OOM吗?

    也许,你想到了个补救方法来挽救程序2,就是每次在处理完list后,我把它设置为null,不让栈帧继续引用着它,咱编写对gc友好的代码,这不就行了,试试:


import java.util.ArrayList;   
import java.util.List;   
  
public class TailRecursionTest2 {   
    public static void main(String[] args) {   
        TailRecursionTest2 t = new TailRecursionTest2();   
        t.a(0);   
    }
   
  
    public void a(int j) {   
        System.out.println(j);   
        j++;   
        if (j == 10000)   
            return;   
        List list = new ArrayList<Integer>(100000);   
        // 对list进行处理   
        list = null;  //gc友好   
        a(j);   
    }
   
}
 

得意洋洋,我跑一下看看,这次跑到4000多次,但是:
   
4289  
4290  
4291  
4292  
java.lang.StackOverflowError   
    at sun.nio.cs.ext.DoubleByteEncoder.encodeArrayLoop(Unknown Source)   
    at sun.nio.cs.ext.DoubleByteEncoder.encodeLoop(Unknown Source)   
    at java.nio.charset.CharsetEncoder.encode(Unknown Source) 

总结:在java里,递归最好咱还是别用,老老实实地while、for;就算递归了,最好递归方法不要new太大的对象,除非你能确定递归的深度不是那么大,否则OOM和堆栈溢出的阴影将笼罩着你。
二维“能量源”(电场、磁场、功率)入射边界设置方法 comsol光学仿真设计相关学习笔记和经验 1. 二维“能量源”(电场、磁场、功率)入射边界设置方法 2.边界条件设置薄膜材料 阅读详情

相关推荐

3U 与 SV630A 伺服实现 CANLINK 通讯

SD410这组参数特别重要,这个32位特别重要,是防止数值乱码的关键。

weixin_42714122的博客 2694

Co、递归调用引发的内存泄漏

前言 我们知道,同步的递归写法,如果在退出递归条件失效时,会快速因为栈溢出导致进程挂掉。而在某些场景下,我们会采用异步的递归写法来规避这个问题: async function recursive() { if( active ) return; // do something await recursive(); } 关键字 await 后面的函数调用可能会跨越多个 ev

weixin_40581617的博客 482

例题讲解拉格朗日乘子法、线性可分支持向量机(SVM)的推导

支持向量机(Support Vector Machine, SVM)的简单推导及例题

zzzssszzzzsz的博客 5681

java 多线程 内存泄露_java内存泄露与内存溢出

java内存泄露与内存溢出基本概念内存泄露:指程序中动态分配内存给一些临时对象,但是对象不会被GC所回收,它始终占用内存。即被分配的对象可达但已无用。内存溢出:指程序运行过程中无法申请到足够的内存而导致的一种错误。内存溢出通常发生于OLD段或Perm段垃圾回收后,仍然无内存空间容纳新的Java对象的情况。从定义上看,内存泄露是内存溢出的一种诱因,不是唯一因素。JAVA中的内存泄露Java中的内存泄...

weixin_39629679的博客 1108

做蛋白组学数据分析,竟然还不会使用DIA-NN软件,走过路过不要错过,进来免费学习!!!

蛋白组学分析工具DIA-NN使用

wcy1995427的博客 9863

从 0 到 1,实战 Power BI 电商销售可视化看板全流程

本文详细介绍了从零开始使用Power BI构建电商销售可视化看板的全流程,涵盖数据准备、建模、可视化设计及高级功能应用。通过实战案例展示如何将复杂销售数据转化为直观图表,帮助电商从业者快速掌握销售趋势、热销产品和用户画像等关键信息,提升数据分析效率。

weixin_29061041的博客 483

深入分析 Java 中的中文编码问题

  深入分析 Java 中的中文编码问题 几种常见的编码格式 为什么要编码 不知道大家有没有想过一个问题,那就是为什么要编码?我们能不能不编码?要回答这个问题必须要回到计算机是如何表示我们人类能够理解的符号的,这些符号也就是我们人类使用的语言。由于人类的语言有太多,因而表示这些语言的符号太多,无法用计算机中一个基本的存储单元—— byte 来表示,因而必须要经过...

yij1986916的博客 4828

Reactor 响应式编程(第一篇:Reactor核心)

响应式:响应式编程: 全异步、消息、事件回调默认还是用当前线程,生成整个流、发布流、流操作.log();//只要不指定线程池,默认发布者用的线程就是订阅者的线程;

moments的博客 1571

java 内存溢出算法_不得不知道的Java内存溢出之在经常调用的方法内不要new大对象...

相信只要你看过Java的书,你一定会看到类似这样的话:千万不要假想内在处理器已经帮你把内存处理好了去做事。看过,真的就只是看过。和C还有C++相比,Java在大部分时间都可以省去了对内存的手动释放操作,不得不说,这个真的挺好使的,因为当初看C++的时候,用个数组,需要释放内在,真心闹不懂啊,这也是为什么当初没有真正走进编程世界的原因吧。但出来混,问题要还的。如果你代码写的不好,或者算法有问题,那么...

weixin_36254537的博客 164

YOLO11涨点优化:loss优化 | 一种新的基于Wasserstein距离的小目标检测评估方法,助力小目标涨点

提出了一种新的基于Wasserstein距离的小目标检测评估方法,通过它们对应的高斯分布计算它们之间的相似性

①答疑群聊服务;②YOLO大模型知识问答系统;③计算机视觉论文生成智能体; 1015

【数字IC验证进阶】正则表达式(Regular Expression)快速入门指南

在芯片开发过程中,正则表达式的使用非常常见。初次上手晦涩难懂,多用几次爱不释手!

悟已往之不谏 知来者之可追 1440

java 要不要捕获内存溢出_不得不知道的Java内存溢出之在经常调用的方法内不要new大对象...

相信只要你看过Java的书,你一定会看到类似这样的话:千万不要假想内在处理器已经帮你把内存处理好了去做事。看过,真的就只是看过。和C还有C++相比,Java在大部分时间都可以省去了对内存的手动释放操作,不得不说,这个真的挺好使的,因为当初看C++的时候,用个数组,需要释放内在,真心闹不懂啊,这也是为什么当初没有真正走进编程世界的原因吧。但出来混,问题要还的。如果你代码写的不好,或者算法有问题,那么...

weixin_30969479的博客 382

如何利用air780e与stm32c8c6进行通信实现给手机发送一条英文短信的功能?

🏆 本文收录于《全栈Bug调优(实战版)》专栏,致力于分享我在项目实战过程中遇到的各类Bug及其原因,并提供切实有效的解决方案。无论你是初学者还是经验丰富的开发者,本文将为你指引出一条更高效的Bug修复之路,助你早日登顶,迈向财富自由的梦想🚀!同时,欢迎大家关注、收藏、订阅本专栏,更多精彩内容正在持续更新中。让我们一起进步,Up!Up!Up!    备注: 部分问题/难题源自互联网,经过精心筛选和整理,结合数位十多年大厂实战经验资深大佬经验总结所得,数条可行方案供所需之人参考。

**My Coding Family** 1237

c语言 尾递归,尾递归的笔记

尾递归,在工作中从来没有用到,仅仅是听过。早晨看文章在Java中谈尾递归–尾递归和垃圾回收的比较的时候,觉得蛮有意思的,尾递归居然可以和JVM的GC放在一起比较,所以搜索了一些文章,作为收藏。如下截取自在Java中谈尾递归–尾递归和垃圾回收的比较,部分文字做了删减,但不影响理解。尾递归优化解决的是内存溢出的问题,而垃圾回收解决的是内存泄露的问题内存泄露:指程序中动态分配内存给一些临时对象,但是对象...

weixin_39877050的博客 183

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

内存泄露 OOM

1:关于java递归调用内存泄露:递归中创建了对象,导致在JVM中维护了一条长长的调用轨迹。 http://www.blogjava.net/vesung/archive/2008/06/03/205474.html 2:从DB中load除了大量的对象,导致OOM, 比如hibernate的外连接的假分页现象。 转载于:https://www.cnblogs.com/hushaowei/...

weixin_34337381的博客 99

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

Java服务假死后续之内存溢出

一、现象分析上篇博客说到,Java服务假死的原因是使用了Guava缓存,30分钟的有效期导致Full GC无法回收内存。经过优化后,已经不再使用Guava缓存,实时查询数据。从短期效果来看,确实解决了无法回收内存的问题,但是服务运行几天后,发现内存又逐渐被占满,Full GC后只能回收一小部分。​编辑切换为居中添加图片注释,不超过 140 字(可选)从上图可以看出,一次Full GC后,老年代基本上没有回收多少内存,占比从99.86%降到99.70%。二、原因排查。

m0_63437643的博客 655

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

Java中的内存溢出和内存泄露

Java中的内存溢出和内存泄露

QYgujingjing的专栏 829

java递归优化_在Java中谈尾递归--尾递归和垃圾回收的比较

我不是故意在JAVA中谈尾递归的,因为在JAVA中谈尾递归真的是要绕好几个弯,只是我确实只有JAVA学得比较好,虽然确实C是在学校学过还考了90+,真学得没自学的JAVA好不过也是因为要绕几个弯,所以才会有有意思的东西可写,另外还有我发现把尾递归如果跟JAVA中的GC比对一下,也颇有一些妙处(发现还没有人特地比较过)(不过后来边写边整理思路,写出来又是另一个样子了)一、首先我们讲讲递归递归的本质是...

weixin_39904612的博客 228

不得不知道的Java内存溢出之在经常调用的方法内不要new大对象

相信只要你看过Java的书,你一定会看到类似这样的话:千万不要假想内在处理器已经帮你把内存处理好了去做事。         看过,真的就只是看过。和C还有C++相比,Java在大部分时间都可以省去了对内存的手动释放操作,不得不说,这个真的挺好使的,因为当初看C++的时候,用个数组,需要释放内在,真心闹不懂啊,这也是为什么当初没有真正走进编程世界的原因吧。         但出来混,问题要还

曹建新 放飞理想,收获希望 1万+

内存溢出与内存泄露知识点总结

内存溢出与内存泄露1. 内存溢出1.1 无限申请对象引起的堆内存溢出1.2 无限调用方法引起的栈内存溢出2. 内存泄露3. 内存抖动 1. 内存溢出 程序在申请内存时,没有足够的内存可以申请,于是程序报错OOM(Out of Memory)。 JVM的内存空间,用的比较多的部分就是堆内存和栈内存,所以内存溢出也分为堆内存溢出和栈内存溢出的情况。 1.1 无限申请对象引起的堆内存溢出 ArrayList list = new ArrayList(); while(true){ list.add(new Ob

wodongx123的博客 344

线上故障之-内存问题

线上故障之-内存问题内存概述内存泄漏(Memory Leak)JAVA中的内存泄露:常见的容易导致内存泄露的点内存溢出(Out Of Memory)模拟内存溢出工具 内存概述 内存泄漏(Memory Leak) 是指程序中已动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。 一般内存泄露的方式: 常发性内存泄漏:发生内存泄漏的代码会被多次执行到,每次被执行时都会导致一块内存泄漏。 偶发性内存泄漏:发生内存泄漏的代码只有在某些特定环境或操作过程

m0_46690280的博客 3801

StackOverflow,OOM和内存泄露的区别

StackOverflow 每当java程序启动一个新的线程时,java虚拟机会为他分配一个栈,java栈以帧为单位保存线程运行状态;当线程调用一个方法时,jvm压入一个新的栈帧到这个线程的栈中,只要这个方法还没返回,这个栈帧就存在。 如果方法的嵌套调用层次太多(如递归调用),随着java栈中的帧的增多,最终导致这个线程的栈中的所有栈帧的大小总和大于-Xss设置的值,而产生StackOverflowError溢出异常。 OutOfMemory 堆内存溢出 java堆用于存放对象的实例,当需要为对象的实例分配

ChenYiRan123456的博客 463

OOM

常见问题怎么解决:   1、内存溢出   2、运行系统很慢   遇到dump文件(对象的形成)+GC(虚拟机的运行情况) 在之前没有垃圾自动回收的日子里,比如C语言和C++语言,我们必须亲自负责内存的申请与释放操作,如果申请了内存,用完后又忘记了释放,比如C++中的new了但是没有delete,那么就可能造成内存泄露。偶尔的内存泄露可能不会造成问题,而大量的内存泄露可能会导致内存溢...

weixin_34315189的博客 113

java递归算法

递归        函数在运行过程中自己调用自己本身称为递归!递归的优点 简化问题,使问题清晰明了,在使用递归时一定要注意两点,第一数据不能太发散,第二层次不鞥太深,数据一旦太发散 层次太深在运行过程中非常消耗内存。故当出现以上两种情况是建议使用循环解决问题。斐波那契数列     0、1、1、2、3、5、8、13、21、34 ........在数学上,斐波纳契数列以如下被以递归的方法定义:

在鬼混的博客 509
上一篇: jvm内存区域划分
下一篇: Hibernate连接池的配置
java85140031
博客等级 码龄18年 34粉丝 51原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值