我有一个应用程序,它会拍摄许多不同的图像,从中制作新图像,然后保存它们以用于制作视频。图像都是PNG,视频是几分钟长,因此程序需要大量内存(每33.33 MS视频播放时间一个图像)。当我处理单个视频时,一切正常。我甚至可以处理几个视频,一切正常。但是,最终,如果我尝试处理1 + n个视频,我会收到一个内存错误。
令我困惑的是这个错误是如何发生的。以下是错误发生的程序部分:
ComposeVideoController cvc = new ComposeVideoController();
boolean made = cvc.setXmlUrl(sourcePath, saveDir, fileId);
cvc = null;
更准确地说,错误发生在ComposeVideoController引用的其中一个框架构造类中。 ComposeVideoController的范围限定为递归运行的单个void方法(如果要制作更多视频)。我已经浏览了ComposeVideoController引用的所有对象,它是构建视频的库的入口点,并确保它们都被设置为null。
如果任何单个视频没有导致outofmemory错误并且在制作任何给定视频后ComposeVideoController超出范围(并设置为null),我怎么能在ComposeVideoController中得到outofmemory错误?
完整递归如下所示。我有一个方法来检查队列中是否有新消息(消息由Socket发送),如果有,则调用处理视频的方法。如果没有,则递归结束:
private void processQueue() {
if(makingVideo)
return;
MakeVideoObject mvo = queue.remove(0);
makingVideo = true;
String[] convertArr = mvo.getConvertArrayCommand();
String sourcePath = convertArr[1];
String fileId = convertArr[2] + ".mp4";
String saveDir = convertArr[3] + System.getProperty("file.separator");
try {
ComposeVideoController cvc = new ComposeVideoController();
boolean made = cvc.setXmlUrl(sourcePath, saveDir, fileId);
cvc = null;
if(made) {
cleanDir(mvo);
}
}
catch(Exception e) {
e.printStackTrace();
}
}
/**
* Moves all the assets off to a storage directory where we can be
* able to recover the video assets if something goes wrong during
* video creation.
*
* @param mvo
*/
private void cleanDir(MakeVideoObject mvo) {
String[] convertArr = mvo.getConvertArrayCommand();
String sourceDir = convertArr[1];
String saveDir = convertArr[3] + System.getProperty("file.separator");
String fileId = convertArr[2];
sourceDir = sourceDir.substring(0, sourceDir.lastIndexOf(System.getProperty("file.separator")));
try {
File f = new File(sourceDir);
File[] files = f.listFiles();
for(File file : files) {
if(file.getName().indexOf(fileId) != -1) {
file.renameTo(new File(saveDir + file.getName()));
}
}
makingVideo = false;
mvo = null;
if(queue.size() > 0) {
processQueue();
}
}
catch(Exception e) {
e.printStackTrace();
}
}
[编辑以显示更多节目]
答案 0 :(得分:0)
几乎就是如果你递归地执行非平凡的代码会发生什么(无论是这个还是经典的堆栈溢出,以先发生者为准) - 递归是非常耗费资源的,应该不惜一切代价避免它。简单地使用迭代算法交换递归将使您的错误消失,很可能
答案 1 :(得分:0)
我发布了一个答案,因为我终于弄明白了,在这种情况下,这有助于其他人在将来尝试诊断内存泄漏。
在我的分析过程中,我可以看到内存中有对象,但是对我来说没有任何意义,因为它们被设置为null。在再次浏览其中一个对象之后,我注意到我已将其声明为静态。因为它是静态的,所以它也有静态成员,其中一个是ConcurrentHashMap ......所以,这些地图都添加了东西,因为对象是静态的,所以对象及其成员永远不会被解引用。关于为什么我几乎从不声明对象静态的另一个教训。
答案 2 :(得分:-1)
使用-Xmx增加内存空间。但是,我建议明确地调用System.gc()关于你得到OutOfMemoryException的地方......如果你把你的其他对象归零,这将有很大的帮助