我正在研究 Apache commons 库中 ExceptionUtils getFullStackTrace 的代码,如下所示:
public static String getFullStackTrace(Throwable throwable) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw, true);
Throwable[] ts = getThrowables(throwable);
for (int i = 0; i < ts.length; i++) {
ts[i].printStackTrace(pw);
if (isNestedThrowable(ts[i])) {
break;
}
}
return sw.getBuffer().toString();
}
我注意到它不会关闭 PrintWriter 并且仅进行自动刷新。
不关闭PrintWriter会导致内存泄漏吗?
我正在使用 FileWriter 登录到一个文件,其中发生了所有异常,并且我想使用上述方法来记录完整的堆栈跟踪。
但后来我用以下内容替换了它,因为我怀疑它会造成内存泄漏:
public static String stackTraceToString(Throwable e) throws Exception {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw,true);
e.printStackTrace(pw);
StringBuilder sb = new StringBuilder();
sb.append(sw.toString());
sw.flush();
sw.close();
pw.close();
return sb.toString();
}
您认为这两种方法对 CPU 和内存的性能如何,哪一种性能更好?
编辑:自定义记录器代码
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;
import javax.faces.context.FacesContext;
public class AppLogger
{
public static String MESSAGE_TYPE_ERROR = "ERROR";
public static String MESSAGE_TYPE_INFO = "INFO";
public static boolean DISABLE_LOG = false;
private static final String _logFilePath = FacesContext.getCurrentInstance().getExternalContext().getInitParameter("LogFilePath");
private static FileWriter _fw;
private AppLogger()
{
}
public static String stackTraceToString(Throwable e) throws Exception {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw,true);
e.printStackTrace(pw);
StringBuilder sb = new StringBuilder();
sb.append(sw.toString());
sw.flush();
sw.close();
pw.close();
return sb.toString();
}
public static void Log(Exception e)
{
if(DISABLE_LOG)
return;
try
{
_fw = new FileWriter(_logFilePath + getFileName(), true);
_fw.write(formatMessage(stackTraceToString(e), AppLogger.MESSAGE_TYPE_ERROR,null));
_fw.close();
}
catch(IOException ex)
{
ex.printStackTrace();
}
catch(Exception ex)
{
ex.printStackTrace();
}
finally
{
releaseResources();
}
}
private static void releaseResources()
{
if(_fw != null)
{
try
{
_fw.close();
_fw = null;
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
private static String getFileName()
{
GregorianCalendar gc = new GregorianCalendar();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
StringBuilder sb = new StringBuilder();
sb.append("logFile.").append(sdf.format(gc.getTime())).append(".log");
return sb.toString();
}
private static String formatMessage(String message, String messageType,String className)
{
GregorianCalendar gc = new GregorianCalendar();
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy hh:mm:ss a");
StringBuilder sb = new StringBuilder();
if(className != null)
sb.append(sdf.format(gc.getTime())).append(" ").append(messageType).append(" ").append(className).append(" : ").append(message).append("\n");
else
sb.append(sdf.format(gc.getTime())).append(" ").append(messageType).append(" ").append(" : ").append(message).append("\n");
return sb.toString();
}
}
最佳答案
在这种情况下,不会。这是 PrintWriter.close
的代码 - 如您所见,它所做的只是关闭它包装的 Writer (out
),并进行一些额外的同步和“错误处理” :
public void close() {
try {
synchronized (lock) {
if (out == null)
return;
out.close();
out = null;
}
}
catch (IOException x) {
trouble = true;
}
}
在这种情况下,它关闭 StringWriter。以下是 StringWriter.close
的代码:
/**
* Closing a <tt>StringWriter</tt> has no effect. The methods in this
* class can be called after the stream has been closed without generating
* an <tt>IOException</tt>.
*/
public void close() throws IOException {
}
正如您所看到的,它什么也没做 - 这是在文档中指定的,而不仅仅是实现细节。
关闭流对于文件(在这种情况下它会停止阻止其他进程写入文件)、网络连接(在这种情况下它会断开连接)以及其他几种类型的流和写入器等非常重要;但是,这对于 StringWriter(以及流等效项 ByteArrayOutputStream
,以及输入等效项 StringReader
和 ByteArrayInputStream
来说并不重要)。
关于java - 记录完整堆栈跟踪性能问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28134160/