用户在上传图片的时候,系统会报异常 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了好几天
: )