OpenCV oom问题解决

现象描述:

        程序运行一小段时间后出现Exception(CvException [org.opencv.core.CvException: cv::Exception: OpenCV(4.5.4) e:\program\opencv-4.5.4\modules\core\src\alloc.cpp:73: error: (-4:Insufficient memory) Failed to allocate xxxx bytes in function 'cv::OutOfMemoryError'])

解决方案

        Decrease Java heap size 减低Java堆内存!!!

知识背景:

        Java的内存管理是由JVM虚拟机完成的,虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域。这些区域都有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,有些区域则是依赖用户线程的启动和结束而建立和销毁。按照《Java虚拟机规范》的规定,Java虚拟机所管理的内存将包含以下几个运行时数据区域:

        程序计数器:线程私有,用于记录当前线程所执行的字节码行号,不存在oom;

        方法区:线程共享,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据;

        Java虚拟机栈:线程私有,它的生命周期与线程相同,主要是负责Java方法执行过程:每个方法被执行的时候都会同时创建一个栈帧用于存储局部变量表、操作栈、动态链接、方法出口等信息;

        本地方法栈:线程私有,与虚拟机栈所发挥的作用非常相似,其区别在于虚拟机栈为虚拟机执行Java方法服务,而本地方法栈则是为虚拟机使用到的 Native方法服务(oracleJDK默认的HotSpot虚拟机将本地方法栈和虚拟机栈合二为一);

        Java Heap堆:线程共享,在虚拟机启动时创建,本区域的目的就是存放对象实例,几乎所有的对象实例都在这里分配内存;

        oom:OutOfMemoryError 内存溢出;

解决历程:

        (1)、首先根据过往经验,看到oom第一反应就是堆内存区域不够,扩展内存时内存不足报oom,故第一反应是设置JVM参数,增大堆内存 -Xms初始堆内存 -Xmx最大堆内存直接上调到4G,但是启动时提示空间不足,无法分配那么大的内存,故将此参数依次下调2G,1G,512m 依然不行,考虑到本来就是oom,且采图较多,每张图片5m以上,再缩小堆空间一是基本无法保证程序运行,二是更会加剧oom的出现,故另寻出路;

        (2)、仔细研究报错信息,均是和第三方库opencv相关,调用的native方法报错,然后调用的opencv是c++编写的,存在内存泄露的可能,所以review代码,保证new出来的相关对象均release掉,经过长时间的排查,解决掉可见的内存释放问题,启动程序,依然存在原问题;(此时思路僵化,问题陷入僵局)

        注:此时基本排除了堆区域的内存溢出以及调用opencv内存泄露问题,且程序计数器区域不存在oom,方法区内存溢出可能性小,问题应该集中在栈区域了,而栈区域最主要的错误为请求的栈深度大于虚拟机所允许的最大深度时的StackOverflowError,只有在虚拟机支持栈区域动态扩展,且在扩展栈时无法申请到足够的内存空间,才可能会抛出oom异常,但是《Java虚拟机规范》明确允许Java虚拟机实现自行选择是否支持栈的动态扩展,而HotSpot虚拟机的选择是不支持扩展。

        (3)、经过技术顾问的指导,从多线程方向入手,因为我们程序涉及线程较多,而HotSpot虚拟机不支持动态扩展,所以除非在创建线程申请内存时就因无法获得足够内存而出现oom异常,否则在线程运行时是不会因为扩展而导致内存溢出的,只会因为栈容量无法容纳新的栈帧而导致StackOverflowError。依据此指导查阅多方资料发现:建立过多线程导致的内存溢出,可以通过减少最大堆(变相的增加了堆以外区域包括栈的空间)和减少栈容量(减小每个线程的占用量以提高线程数)来换取更多的线程以避免oom。

未尽事宜:

        虽然了解了其原理,且给出了初版的解决方案,但是在系统内存剩余空间在5-8G的情况下,堆空间只能分配256m才能暂时保证程序的运行,显然有些不合理,还需要继续了解JVM内存的分配机制甚至直接内存的使用情况及原理以进一步优化程序,彻底保证程序的顺利运行。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值