Windows
如果 Windows Tomcat 來自 webapp 與來自 JVM,為什麼 Windows Tomcat 處理標準輸出的方式不同?
我正在使用捆綁的 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 的內容,我認為序列將是這樣的。
- 啟動 JVM 的新程序,傳遞“stdin”、“stdout”和“stderr”文件描述符。這些通常由呼叫 shell 設置,並通過 fork/exec 系統呼叫傳遞給 JVM。(或任何 Windows 等價物……)但在這種情況下,有一些包裝腳本或本機應用程序在 JVM 啟動之前將“stdout”重定向到“jakarta_service_xxx.log”。
- JVM 創建了一些內部日誌系統(在本機程式碼中實現),GC 和其他 JVM 服務將使用這些系統進行 JVM 日誌記錄。這將使用“stdout”或“stderr”文件描述符。
- JVM 創建 PrintStream(OutputStream) 對象,這些對象包裝“stdout”和“stderr”文件描述符,並分別設置
java.lang.System.out
和java.lang.System.err
設置這些對象。- JVM呼叫Tomcat
main
方法來啟動Tomcat。- 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”輸出分開通常是一個好主意。可能有配置文件等允許您更改它…如果您願意。