我的Java應用程序使用JNI調用C編寫的庫。此本機庫將錯誤記錄到stderr,但我想通過我的log4j記錄器以某種方式重定向錯誤流。這可能嗎?通過log4j發送JNI C stderr/stdout
C庫是外部的 - 我沒有源代碼,所以無法更改它。
感謝
我的Java應用程序使用JNI調用C編寫的庫。此本機庫將錯誤記錄到stderr,但我想通過我的log4j記錄器以某種方式重定向錯誤流。這可能嗎?通過log4j發送JNI C stderr/stdout
C庫是外部的 - 我沒有源代碼,所以無法更改它。
感謝
注:我沒有嘗試過這個答案;因人而異。
POSIX方法freopen
將更改與流關聯的底層文件。正如手冊頁所述:「freopen()函數的主要用途是更改與標準文本流(stderr,stdin或stdout)關聯的文件」。
所以,你可以創建自己的JNI庫,它只是將流重定向到一個文件中。 然而,有幾個嚴重的障礙,以使這項工作:
System.out
和 更改爲其他內容。最後一點是迄今最大的:stdio寫入OS級文件描述符。您將不得不創建一些Java級代碼來讀取該描述符並寫入日誌。我的第一個想法是,你必須使用一個命名管道,然後啓動一個新的Java線程來讀取該管道。但是這不能移植到不同的操作系統,並且你會在你的程序配置中管理管道名稱。
假設這是一個服務器程序,並且本身並不處理標準IO流,我認爲最好的解決方案是使用控制檯記錄器配置Log4J,並將所有控制檯輸出重定向到一個文件。
或者與編寫庫的人交談,讓他們添加可配置的日誌記錄。
我的C是有點生疏,但它是可能的,因爲你可以從通過JNI一個C中調用PrinStream方法。但是當流寫入時,你必須找到一種方法來掛鉤。
更新:這可以幫助你與掛鉤到標準輸出從C:
http://www.gnu.org/software/hello/manual/libc/Hook-Functions.html
謝謝,但不幸的是我不能改變C庫,因爲它不是我的。 – dogbane 2009-12-30 22:57:00
JNI圖層是您的應用程序的一部分還是外部工具包的一部分? – PSpeed 2009-12-30 23:09:17
這也是外部工具包的一部分。 – dogbane 2009-12-30 23:17:09
您調用外部代碼的粒度是多少,以及有多少數據來回傳遞?換句話說,你能把這項工作作爲一個孩子的過程嗎?重定向你不能控制的C代碼的stdout或stderr是非常困難的。我之前認爲我已經完成了它,但自從我編寫了那種C代碼以來,至少已經有10年了,我可以在網上找到的所有代碼都是關於將其重定向到文件的。 – PSpeed 2009-12-30 23:32:19