![](/img/trans.png)
[英]I am getting “Exception in thread ”main" java.lang.NullPointerException even though no values are set to null
[英]Java Throwing OutOfMemory Even Though (I Think) I've Set References To Null
我有一個應用程序,該應用程序可以拍攝許多不同的圖像,從它們中制作新圖像,然后將其保存以用於制作視頻。 圖像都是PNG格式,而視頻則是幾分鍾,因此該程序需要大量內存(每33.33 MS視頻播放時間一張圖像)。 當我處理單個視頻時,一切正常。 我什至可以處理多個視頻,而且一切正常。 但是,如果我嘗試處理1 + n個視頻,最終會出現內存不足的錯誤。
使我困惑的是該錯誤是如何發生的。 這是程序中發生錯誤的部分:
ComposeVideoController cvc = new ComposeVideoController();
boolean made = cvc.setXmlUrl(sourcePath, saveDir, fileId);
cvc = null;
更准確地說,該錯誤發生在ComposeVideoController引用的其中一個幀構造類中。 ComposeVideoController的作用域是遞歸運行的單個void方法(如果要制作更多視頻)。 我已經遍歷了ComposeVideoController引用的所有對象,這是構建視頻的庫的入口點,並確保它們也都設置為null。
當制作任何給定視頻后,任何單個視頻都不會引起內存不足錯誤並且ComposeVideoController超出范圍(並將其設置為null)時,如何在ComposeVideoController中出現內存不足錯誤?
完整的遞歸如下所示。 我有一種方法可以檢查隊列中是否有新消息(消息是由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();
}
}
[編輯以顯示更多程序]
如果您遞歸地執行非平凡的代碼(這是經典堆棧溢出還是經典堆棧溢出,以先發生者為准),那幾乎就是什么-遞歸非常占用資源,應該不惜一切代價避免它。 只需使用迭代算法交換您的遞歸,您的錯誤就很可能消失
我發布了答案,因為我終於弄清楚了,如果情況不妙,這將有助於其他人將來嘗試診斷內存泄漏。
在分析過程中,我可以看到內存中保留有對象,但是對我來說這沒有意義,因為它們被設置為null。 再次瀏覽了其中一個對象之后,我注意到我已將其聲明為靜態。 因為它是靜態的,所以它也有靜態成員,其中之一是ConcurrentHashMap ...因此,那些Map中添加了一些東西,並且由於對象是靜態的,因此永遠不會取消引用該對象及其成員。 關於為什么我幾乎從不聲明對象靜態的另一個教訓。
使用-Xmx可以增加您的內存空間。 而且,我建議您在正確的位置顯式地調用System.gc(),以獲取OutOfMemoryException ...如果要清空其他對象,這將對您有很大幫助
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.