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没有释放足够用的内存,在下面释放内存并抛出异常;
再次执行功能代码时,暂时够一次使用;
再次执行功能代码时,内存又不够用了;