簡體   English   中英

殺死Java進程時關閉BufferedReader和BufferedWriter

[英]Closing BufferedReader and BufferedWriter when killing Java process

我有一個Java程序,可以在更新日志記錄信息的同時讀取過濾后的數據並將其寫入新文件。 當我將其作為jar執行時,它將一直運行到我終止進程為止。

如何確保在終止該進程時關閉BufferedReader和BufferedWriter以防止內存泄漏?

我嘗試過使用try ... finally塊方法,如其他人所建議的那樣,但這會在程序仍在運行時關閉流。 提前致謝。

FileWatcher.java

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;

import java.io.*

public class FileWatcher implements Runnable
{
  boolean running = true;
  File file;
  BufferedReader reader;
  BufferedWriter writer;
  String pathToLog, pathToOutput;

  public FileWatcher(String pathToLog, String pathToOutput)
  {
    this.pathToLog = pathToLog;
    this.pathToOutput = pathToOutput;
  }

  public void run()
  {
    try
    {
      file = new File(pathToOutput);
      reader = new BufferedReader(new FileReader(pathToLog));
      writer = new BufferedWriter(new FileWriter(pathToOutput));

      if (!file.exists())
      {
        file.createNewFile();
      }
    }
    catch (FileNotFoundException e)
    {
      e.printStackTrace();
    }
    catch (IOException e)
    {
      e.printStackTrace();
    }

    String line = null;

    System.out.println("Running...");
    while (running)
    {
      try
      {
        /* For each packet logged */
        for (int i = 0; i < 7; i++)
        {
          line = reader.readLine(); //Analyse text in line

          /* If no text then break */
          if (line == null)
          {
            break;
          }

          /* If the line begins with valid IP address then break to find Src and Dest IP */
          if (line.startsWith("192", 22))
          {
            break;
          }
        }

        /* If line is not null then filter out the Source IP and Destination IP */
        if (line != null)
        {
          int lastIndexOfSrcIP = StringUtils.ordinalIndexOf(line, ":", 3); // Position to stop reading Source IP
          int firstIndexOfDestIP = StringUtils.ordinalIndexOf(line, ">", 1) + 2; // Position to start reading Destination IP
          int lastIndexOfDestIP = StringUtils.ordinalIndexOf(line, ":", 4); // Position to stop reading Destination IP

          String sourceIP = line.substring(22, lastIndexOfSrcIP); // Source IP
          String destinationIP = line.substring(firstIndexOfDestIP, lastIndexOfDestIP); // Destination IP

          /* Check if Source IP is the IP address of the node  we are running Snort on
           * if so then don't append to malicious clients file */
          if (!(sourceIP.equals("192.168.7.5")))
          {
            //If Source IP is not in file then add it
            if (!(FileUtils.readFileToString(file).contains(sourceIP)))
            {
              writer.write(sourceIP + "\n");
              writer.flush();
            }

            System.out.println(sourceIP + "\t" + destinationIP);
          }
        }
        else
        {
          //Sleep whilst there are no new logging alert information
          try
          {
            Thread.sleep(1000);
          }
          catch (InterruptedException e)
          {
            running = false;
            writer.close();
            reader.close();
          }
        }
      }
      catch (IOException e)
      {
        e.printStackTrace();
      }
    }
  }
}

Main.java

public class Daemon
{
  public static void main(String[] args)
  {
    String pathToLog = args[0];
    String pathToOutput = args[1];

    Thread daemon = new Thread(new FileWatcher(pathToLog, pathToOutput));
    daemon.start();
  }
}

為了直接回答您的問題,我將在構造函數中創建文件,這使您的代碼快速失敗,並讓調用者知道這將無法正常工作。

然后,我將有一個try / finally塊,其中包裝了所有代碼,例如

public void run() {
    try {
        run0();
    } catch(Throwable t) {
        System.err.println("Process dying");
        t.printStackTrace();
    } finally {
        // close all resources
    }
}

private void run0() throws Stuff... {
    // does the real work
}

如何確保在終止該進程時關閉BufferedReader和BufferedWriter以防止內存泄漏?

當您殺死一個進程時,操作系統將回收所有進程資源,因此無論您如何編碼,都不會發生內存泄漏。 您可以獲得的唯一資源泄漏是留下了不需要的臨時文件。

BTW

  • 調用FileWriter時,它將創建一個新文件或根據需要截斷。 沒有一點檢查該文件是否仍然存在,因為即使該文件已被刪除(極不可能),您也不會使用剛創建的文件。

  • 我不會只在main的末尾創建一個新線程,因為這無濟於事。

  • 另外,如果它是守護程序線程,我只會調用線程daemon程序。 給它起一個誤導性的名稱可能會造成混淆。

如果您使用的是Java 7或更高版本,則可以使用try-with-resources聲明您的讀取器/寫入器,並且在您終止該進程時它們應自動關閉。

在您的示例中,它看起來像這樣:

try(reader = new BufferedReader(new FileReader(pathToLog));
    writer = new BufferedWriter(new FileWriter(pathToOutput));) {
        ...
}

暫無
暫無

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

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