簡體   English   中英

Java不釋放內存

[英]Java does not free memory

我有一個守護程序,該程序讀取文件的內容,然后將其壓縮並將其寫入較小的.tar.gz文件。

由於某種原因,即使我已經釋放(或我認為已經擁有)所有已使用的內存,Java仍繼續分配內存。 我的代碼/推理有什么問題?

FileOutputStream fos    = null;
GZIPOutputStream gzipos = null;
OutputStreamWriter osw  = null;

BufferedWriter bw = null;
while (true) {
    if (f.length() != 0) {
        if (outputfile == null) {
            outputfile = outputfileroot + "_" + outputPart + ".tar.gz";

            fos = new FileOutputStream(outputfile);
            gzipos  = new GZIPOutputStream(fos);
            osw = new OutputStreamWriter(gzipos);
            bw  = new BufferedWriter(osw);
        }
        else if (new File(outputfile).length() > maxLengthOutputFile) {
            bw.flush();
            osw.flush();
            gzipos.flush();
            fos.flush();
            bw.close();
            osw.close();
            gzipos.close();
            fos.close();

            bw  = null;
            osw = null;
            gzipos  = null;
            fos = null;

            System.gc();

            System.out.println("Finished writing " + outputfileroot + "_" + outputPart + ".tar.gz");

            outputfile = outputfileroot + "_" + ++outputPart + ".tar.gz";
            fos     = new FileOutputStream(outputfile);
            gzipos  = new GZIPOutputStream(fos);
            osw     = new OutputStreamWriter(gzipos);
            bw      = new BufferedWriter(osw);
        }

        /**
         * Read the entire file
         */
        BufferedReader br = new BufferedReader(new FileReader(f));
        String line;
        while ((line = br.readLine()) != null) {
            // will send the content to another thread, so I need to read it line by line
            bw.write(line + "\r\n");
        }
        br.close();
        br = null;
        bw.flush();

        /**
         * Empty it
         */
        FileWriter fw = new FileWriter(f);
        fw.write("");
        fw.flush();
        fw.close();
        fw = null;
    }

    Thread.sleep(1000);
}

你太過分了。 所有的null設置和gc()調用實際上都沒有幫助,並且刷新和關閉的次數是您實際需要的幾倍。 另外,您根本不需要使用讀取器和寫入器。 所有可以簡化為:

GZIPOutputStream gzipos = null;
while (true)
{
    if (f.length() != 0)
    {
        if (outputfile == null)
        {
            outputfile = outputfileroot + "_" + outputPart + ".tar.gz";
            gzipos = new GZIPOutputStream(new FileOutputStream(outputfile));
        }
        else
        {
            if (new File(outputfile).length() > maxLengthOutputFile)
            {
                gzipos.close();
                System.out.println("Finished writing " + outputfileroot + "_" + outputPart + ".tar.gz");
                outputfile = outputfileroot + "_" + ++outputPart + ".tar.gz";
                gzipos = new GZIPOutputStream(new FileOutputStream(outputfile));
            }
        }

        /**
         * Read the entire file
         */
        InputStream in = new FileInputStream(f);
        byte[] buffer = new byte[8192];
        int count;
        while ((count = in.read(buffer)) > 0)
        {
            gzipos.write(buffer, 0, count);
        }
        in.close();
        gzipos.flush();
        /**
         * Empty it
         */
        f.createNewFile();
    }
    Thread.sleep(1000);
}

我對您的評論沒有任何意義,“會將內容發送到另一個線程,所以我需要逐行閱讀”。 此代碼中沒有線程,您不需要逐行輸入。

我也很好奇它如何與生成輸入文件的內容進行交互。 我認為您應該重命名輸入文件,並在決定復制它時立即在其位置創建一個新的空文件,而不是在復制步驟之后。

不能僅僅因為不再引用對象而將它們從內存中釋放出來。 JVM決定何時運行其“垃圾回收”,從而釋放內存。 但是除非需要,否則通常不會運行垃圾回收。 有關更多信息,您可以在此頁面上看到有關該主題的信息

您可以調用System.gc()顯式調用垃圾收集器(鏈接中的第7點),但是不必運行它。

System.gc()發送垃圾回收請求。 運行時決定是執行它還是忽略所述請求。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM