簡體   English   中英

引發NullPointerException

[英]Impossible NullPointerException thrown

在幾年前編寫的一個Web服務器項目中,我偶爾會遇到一個非常奇怪的-在我看來-不可能的NullPointerException 它以實用程序方法發生,用於在控制台上記錄輸出。

這是該方法的錯誤摘錄:

try {
    Encoder encoder = Base64.getEncoder();
    if(logWriter != null) {
        logWriter.write(String.valueOf(System.currentTimeMillis()));
        logWriter.write(" ");
        logWriter.write(String.valueOf(level));
        logWriter.write(" ");
        logWriter.write(encoder.encodeToString(Thread.currentThread().getName().getBytes()).replaceAll("(?:\\r\\n|\\n\\r|\\n|\\r)", ""));
        logWriter.write(" ");
        logWriter.write(encoder.encodeToString(log.getBytes()).replaceAll("(?:\\r\\n|\\n\\r|\\n|\\r)", ""));
        logWriter.write("\r\n");
        logWriter.flush();
    }

    lastWriterActivity = System.currentTimeMillis();
} catch (IOException e) {
    println("Failed to write log to file: " + e, Color.RED);

    try {
        logWriter.close();
    } catch (IOException e1) {
        println("### Possible resource leak; unable to close log writer", Color.RED);
    }

    logWriter = null;
}

其中logWriterBufferedWriter NPE被拋出在調用logWriter.close()的第一個catch塊中。

但是:當logWriter為!= null ,如何在try塊中引發IOException Base64.getEncoder()無法引發IOException並且沒有其他代碼可以執行。

這是我的堆棧跟蹤:

Exception in thread "connection_0:0:0:0:0:0:0:1@1544725509" java.lang.NullPointerException
at org.jpuzzle.main.Logger.write(Logger.java:347)
at org.jpuzzle.main.Logger.verbose(Logger.java:187)
at org.jpuzzle.protocol.http.HttpRequest.onRequest(HttpRequest.java:1090)
at org.jpuzzle.network.ConnectionListener$Connection.proceed(ConnectionListener.java:438)
at org.jpuzzle.network.ConnectionListener$Connection.run(ConnectionListener.java:408)

我的方法是synchronized ,因此互斥不會造成任何困難,而且我不知道為什么會發生這種情況。

簡短答案:

重寫您的catch塊,以避免NullPointerException

try {
  if(logWriter != null) {
    logWriter.close();
  }
} catch (IOException e1) {
    println("### Possible resource leak; unable to close log writer", Color.RED);
}

長答案:

是的,logWriter是靜態的。...不同步會阻止對方法執行並行方法嗎?

沒有。

需要證明嗎?

運行此代碼:

public class NowImFeelingZombified {
  static Object logWriter = new Object();

public static void main(String[] args) {
    final NowImFeelingZombified zombie1 = new NowImFeelingZombified();
    final NowImFeelingZombified zombie2 = new NowImFeelingZombified();

    Thread t1 = new Thread("zombie1 ") {
        @Override
        public void run() {
            zombie1.syncedMethod();
        }
    };
    Thread t2 = new Thread("zombie2 ") {
        @Override
        public void run() {
            zombie2.syncedMethod();
        }
    };
    t1.start();
    t2.start();
}

private synchronized void syncedMethod() {
    try {
        System.out.println(Thread.currentThread().getName() + logWriter.toString());

        Thread.sleep(2000L);

        System.out.println(Thread.currentThread().getName() + logWriter.toString());

        logWriter = null;
    }
    catch (InterruptedException e) {
    }
  }
}

輸出是這樣的:

zombie1 java.lang.Object@1c34796b
zombie2 java.lang.Object@1c34796b
zombie1 java.lang.Object@1c34796b
Exception in thread "zombie2 " java.lang.NullPointerException
    at NowImFeelingZombified.syncedMethod(NowImFeelingZombified.java:44)

Howsa?

同步方法將獲得對該方法的調用者的鎖定。 含義t1不在乎t2 (當然也logWriter )。

而已。 在這里閱讀全文

另外,很久以前,我為我一直使用的Util類編寫了這樣的5襯里。 它使我Closeables編寫用於關閉Closeables catch

public static void close(Closeable closeable) {
    if (closeable != null) {
        try {
            closeable.close();
        }
        catch (IOException e) {
            //logging
        }
    }
}

無論如何,Java 1.7引入了您可能想探索的AutoCloseable (由BufferedWriter實現)。

暫無
暫無

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

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