用戶在上傳圖片的時候,系統會報異常 insufficient memory case 4,追蹤代碼發生在jdk中 image.io 的 read() 方法。這是一個耽擱了好久的bug,客戶反饋了好幾回,找了幾回方向都沒處理好,搞得客戶很不耐煩,我本身也很傷腦筋,差點就投降了。
我嘗試過本地測試復現,可是也只是在多線程同時併發纔會出現,線上出現該異常的時候,只有一我的在使用,因此當時也是很疑惑。對於內存不足來講,這個和內存溢出OutOfMemoryError是不同的,後者每每是分配給JVM的內存不足,前者實際上可能更可能是物理本地內存不足(固然,這是後來才知道的)
其中有段回覆是這樣說明的:「
Summing it up, I'm going to guess that the situation is that the JVM has enough memory allocated to it by the OS, but the JPEG decoder which is (probably) calling native code of libjpeg, and libjpeg is unable to obtain more free memory from the OS. You may want to look at how much (virtual) memory that the OS has free at the time you encounter this error. If my guess is correct, it would mean that you'll need to reduce the amount of parallel processing, and adding more heap (-Xmx) to the JVM probably isn't going to alleviate the situation.」
能夠看到,他說可能的緣由在於JVM的內存是足夠的,可是在調用一些其餘非Java代碼的接口,即native方法時,這些方法沒法從系統中獲取到足夠使用的物理內存,因而形成了該異常。方向有了,看看服務器總體物理內存的使用狀況。
因而我在客戶告知我異常時,登錄服務器查看了內存的使用,服務器是8G內存,當時顯示已使用內存高達7.9G(吃驚,怎麼這麼高),其中有個進程佔用高達5G以上,是誰呢?sqlserver.exe(當時就驚了)
這是由於sqlserver.exe默認使用的策略是用多少內存佔多少內存,只有服務器內存不足纔會釋放一些。這些內存多用來進行 「查詢出的數據緩存」 和 「執行命令緩存」,因此解決方法其實很簡單,調整sqlserver的可以使用物理內存便可(圖來自網絡):
我把sqlserver的內存使用限制在了3G,以後問題便迎刃而解。那句話怎麼說來着,改代碼兩分鐘,DEBUG兩小時,說得真沒錯,關鍵是我DEBUG了好幾天
: )