javacv物理内存溢出

java.lang.OutOfMemoryError: Physical memory usage is too high: physicalBytes (602M) > maxPhysicalBytes (600M)
	at org.bytedeco.javacpp.Pointer.deallocator(Pointer.java:588)
	at org.bytedeco.javacpp.Pointer.init(Pointer.java:124)
	at org.bytedeco.javacpp.avcodec$AVPacket.allocate(Native Method)
	at org.bytedeco.javacpp.avcodec$AVPacket.<init>(avcodec.java:1516)
	at org.bytedeco.javacv.FFmpegFrameGrabber.startUnsafe(FFmpegFrameGrabber.java:699)
	at org.bytedeco.javacv.FFmpegFrameGrabber.start(FFmpegFrameGrabber.java:690)
	at com.nst.socket.startup.VideoTool.randomGrabberFFmpegImage(VideoTool.java:40)
	at com.nst.socket.startup.VideoMessageHandler.getCoverImageFromVideo(VideoMessageHandler.java:107)
	at com.nst.socket.startup.SocketServerConsumer.handleMessageObject(SocketServerConsumer.java:273)
	at com.nst.socket.startup.SocketServerConsumer.lambda$readFromInputStreamWithTimeout$0(SocketServerConsumer.java:108)

JVM参数如下

-Xms300m -Xmx300m

查看Pointer.java看一下参数值的确定

static {
        String s = System.getProperty("org.bytedeco.javacpp.nopointergc", "false").toLowerCase();
        s = System.getProperty("org.bytedeco.javacpp.noPointerGC", s).toLowerCase();
        if (s.equals("true") || s.equals("t") || s.equals("")) {
            referenceQueue = null;
            deallocatorThread = null;
        } else {
            referenceQueue =  new ReferenceQueue<Pointer>();
            deallocatorThread = new DeallocatorThread();
        }

        long m = Runtime.getRuntime().maxMemory();
        s = System.getProperty("org.bytedeco.javacpp.maxbytes");
        s = System.getProperty("org.bytedeco.javacpp.maxBytes", s);
        if (s != null && s.length() > 0) {
            try {
                m = parseBytes(s);
            } catch (NumberFormatException e) {
                throw new RuntimeException(e);
            }
        }
        maxBytes = m;

        m = 2 * Runtime.getRuntime().maxMemory();
        s = System.getProperty("org.bytedeco.javacpp.maxphysicalbytes");
        s = System.getProperty("org.bytedeco.javacpp.maxPhysicalBytes", s);
        if (s != null && s.length() > 0) {
            try {
                m = parseBytes(s);
            } catch (NumberFormatException e) {
                throw new RuntimeException(e);
            }
        }
        maxPhysicalBytes = m;

        int n = 10;
        s = System.getProperty("org.bytedeco.javacpp.maxretries");
        s = System.getProperty("org.bytedeco.javacpp.maxRetries", s);
        if (s != null && s.length() > 0) {
            try {
                n = Integer.parseInt(s);
            } catch (NumberFormatException e) {
                throw new RuntimeException(e);
            }
        }
        maxRetries = n;
    }

因此,根据Xmx300m,最大maxPhysicalBytes=600m就是提示信息中的限制。一般情况下测试600m是不会内存溢出的,还是出现了意外。
一般会给出两种解决方案,专门修改maxPhysicalBytes参数,一个是扩大这个数据,一个是不限制内存增长;
增大这个参数:

-Dorg.bytedeco.javacpp.maxbytes=8G -Dorg.bytedeco.javacpp.maxphysicalbytes=8G

不做内存检查

-Dorg.bytedeco.javacpp.maxbytes=0G -Dorg.bytedeco.javacpp.maxPhysicalBytes=0G

根据参数的内存检查

this.deallocator = deallocator;
            DeallocatorReference r = deallocator instanceof DeallocatorReference ?
                    (DeallocatorReference)deallocator :
                    new DeallocatorReference(this, deallocator);
            int count = 0;
            long lastPhysicalBytes = maxPhysicalBytes > 0 ? physicalBytes() : 0;
            synchronized (DeallocatorThread.class) {
                try {
                	// 如果可以重试且内存溢出,尝试回收内存
                    while (count++ < maxRetries && ((maxBytes > 0 && DeallocatorReference.totalBytes + r.bytes > maxBytes)
                                         || (maxPhysicalBytes > 0 && lastPhysicalBytes > maxPhysicalBytes))) {
                        if (logger.isDebugEnabled()) {
                            logger.debug("Calling System.gc() and Pointer.trimMemory() in " + this);
                        }
                        // try to get some more memory back
                        System.gc();
                        Thread.sleep(100);
                        trimMemory();
                        lastPhysicalBytes = maxPhysicalBytes > 0 ? physicalBytes() : 0;
                    }
                } catch (InterruptedException ex) {
                    // reset interrupt to be nice
                    Thread.currentThread().interrupt();
                } catch (UnsatisfiedLinkError e) {
                    // old binaries with physicalBytes() or trimMemory() missing -> ignore for backward compatibility
                    if (logger.isDebugEnabled()) {
                        logger.debug(e.getMessage());
                    }
                }
				// 内存仍然溢出,释放内存并抛出异常
                if (maxBytes > 0 && DeallocatorReference.totalBytes + r.bytes > maxBytes) {
                    deallocate();
                    throw new OutOfMemoryError("Failed to allocate memory within limits: totalBytes ("
                            + formatBytes(DeallocatorReference.totalBytes) + " + " + formatBytes(r.bytes) + ") > maxBytes (" + formatBytes(maxBytes) + ")");
                } else if (maxPhysicalBytes > 0 && lastPhysicalBytes > maxPhysicalBytes) {
                    deallocate();
                    throw new OutOfMemoryError("Physical memory usage is too high: physicalBytes ("
                            + formatBytes(lastPhysicalBytes) + ") > maxPhysicalBytes (" + formatBytes(maxPhysicalBytes) + ")");
                }
                if (logger.isDebugEnabled()) {
                    logger.debug("Registering " + this);
                }
                r.add();
            }

我遇到的情况是,上面的gc没有释放足够用的内存,在下面释放内存并抛出异常;
再次执行功能代码时,暂时够一次使用;
再次执行功能代码时,内存又不够用了;

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值