这几天在查一个内存溢出的问题,虽然不能确定到底是不是溢出了,但是jvm占的内存却会疯狂增长,当然是在没有设置 -Xmx 的前提下。
问题主题代码以被抽出,构成测试用例如下:
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javax.imageio.ImageIO;
public class ImageIOTest {
public static void main(String[] args) throws Exception {
int nums = 800;
//for (int i = 0; i < nums; i++) {
// new Thread(new Tt1()).run(); //单线程
//}
new Thread(new DoMutil(30, nums)).run(); // 并发
Thread.sleep(1000000);
}
}
class DoMutil implements Runnable {
int threadNum = 1;
int nums = 1;
public DoMutil(int threadNum, int nums) {
this.threadNum = threadNum;
this.nums = nums;
}
@Override
public void run() {
ExecutorService executorService = Executors
.newFixedThreadPool(threadNum);
for (int i = 0; i < nums; i++) {
executorService.execute(new Tt1());
}
}
}
class Tt1 implements Runnable {
static String xx = "d:/x/xxx.png";
public void run() {
try {
BufferedImage image = ImageIO.read(new File(xx));
image.flush();
int width = image.getWidth();
Thread.sleep(100);
} catch (IOException e1) {
} catch (InterruptedException e) {
}
}
}
运行条件:1.
放个图片在 d:/x/xxx.png 。我的图片大小为600多k。
运行结果(win7 64位 jdk1.7.0_17): 1.单线程运行时,内存使用正常。 2. 30个并发执行时,内存使用近1G。
虽然这个1G的被jvm占用的内存,并非“使用的堆”大小,而是“堆”大小,但是机器的内存确实被用掉,影响了其他的系统。
经过各种分析。。。jvisualvm。。。gc日志。。。。均为发现任何问题。
-----------------------------------------------华丽分割--------------------------苦逼寻找-----------------------------------------
昨日,有人在办公群里问newWorkStealingPool 和newCachedThreadPool的区别,遂下载jdk1.8,把Executors源码给扫了,解释之。。
------------------------------转折点 如上-------------------------------
今日继续做测试,执行上述程序,无意间发现内存不再被使用这么多了,而是正常的270M左右。
疑惑不解~
突然发现了这个
我X。。。jdk1.8.。。。
于是,又进行了多次测试,果然,jdk8是正常的,jdk7就是会吃掉很大内存。
-----------------------------结尾----------------------------
至此,基本上找到了根源。。。估计jdk7中,关于imageIO在线程池中并发使用时,会出现一些问题。当然了,问题就不深究了。
咱也没看过jvm源码。。。
PS: 这个问题,还没最终解决,因为还没上线到linux生产环境中,但是,这块应该还是存在问题的,所以,遇到该问题的小伙伴,可以参考下哈~哈哈