繁体   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