Windows

如果 Windows Tomcat 來自 webapp 與來自 JVM,為什麼 Windows Tomcat 處理標準輸出的方式不同?

  • January 16, 2010

我正在使用捆綁的 Windows 服務執行器在 Windows 下執行 Tomcat 6。我似乎有以下行為:

  • 如果我的一個 Web 應用程序寫入標準輸出(例如,通過 System.out.println),則此輸出會逐字顯示在標題為 stdout_xxx.log 的日誌中。
  • 如果 jvm 本身寫入標準輸出(就像啟用 -XX:+PrintCompilation 一樣),則此輸出會顯示在標題為 jakarta_service_xxx.log 的日誌中。

此外, jakarta_service_xxx.log 不是標準輸出的直接轉儲;相反,似乎有些東西正在攔截標準輸出並通過 java 日誌記錄重定向。因此,沒有 Tomcat 的 JVM 通常會列印

283 s java.lang.StringBuffer::length (5 bytes)

jakarta_service_xxx.log 中顯示的是:

[2010-01-15 17:07:15] [info] 283
[2010-01-15 17:07:15] [info]  s    
[2010-01-15 17:07:15] [info]  java.lang.StringBuffer::
[2010-01-15 17:07:15] [info] l
[2010-01-15 17:07:15] [info] e
[2010-01-15 17:07:15] [info] n
[2010-01-15 17:07:15] [info] g
[2010-01-15 17:07:15] [info] t
[2010-01-15 17:07:15] [info] h
[2010-01-15 17:07:15] [info]  (5 bytes)

你能解釋一下為什麼 stdout 在這兩種情況下會受到不同的對待嗎?或者,關於如何從 -XX:+PrintCompilation 獲取 JVM 輸出以顯示在 stdout.log 中的任何提示,而不是上述瘋狂?

確定沒有深入研究 Tomcat 的內容,我認為序列將是這樣的。

  1. 啟動 JVM 的新程序,傳遞“stdin”、“stdout”和“stderr”文件描述符。這些通常由呼叫 shell 設置,並通過 fork/exec 系統呼叫傳遞給 JVM。(或任何 Windows 等價物……)但在這種情況下,有一些包裝腳本或本機應用程序在 JVM 啟動之前將“stdout”重定向到“jakarta_service_xxx.log”。
  2. JVM 創建了一些內部日誌系統(在本機程式碼中實現),GC 和其他 JVM 服務將使用這些系統進行 JVM 日誌記錄。這將使用“stdout”或“stderr”文件描述符。
  3. JVM 創建 PrintStream(OutputStream) 對象,這些對象包裝“stdout”和“stderr”文件描述符,並分別設置java.lang.System.outjava.lang.System.err設置這些對象。
  4. JVM呼叫Tomcatmain方法來啟動Tomcat。
  5. Tomcat 向“stdout_xxx.log”打開一個新的 FileOutputStream 並用於java.lang.System.setOut()更新java.lang.System.out. 如果每個 webapp 有不同的“stdout_xxx.log”文件,那麼很可能 Tomcat 已經實現了一個聰明的輸出流代理,它根據執行緒組或其他東西將輸出解復用到不同的日誌文件……

我懷疑 JVM 日誌記錄根本沒有使用 java.util.Logging …或任何 Java 程式碼。看起來就是這樣。我這樣說是因為我認為如果 JVM 試圖在某些時候呼叫 Java 程式碼,它會陷入困境;例如在 GC 的關鍵點。但我可能錯了……

至於為什麼會發生這種情況,我認為它正在發生,因為將來自 webapps 和 jvm / tomcat 核心的“System.out/err”輸出分開通常是一個好主意。可能有配置文件等允許您更改它…如果您願意。

引用自:https://serverfault.com/questions/103293