各位前辈,你们好,最近公司项目遇到了头疼的问题,web应用运行后一天要重新启动服务6次~8次,原因都是webLogic报内存不足。于是我开始进入优化阶段,在代码中发现了如下代码体,请问是否需要改写?byte[] byteGz = .....
Map<String,BufferedInputStream> map = new HashMap<String,new BufferedInputStream>();
map.put("a",new BufferedInputStream(new ByteArrayInputStream(byteGz)));
...
之后的逻辑会调用void createPdf(Map<String,BufferedInputStream> map)方法生成pdf文件存放到数据库中,BufferedInputStream流对象由于没有任何指向,因此始终没有代码实现流的关闭。
请问:
1、这种代码实现的方式会不会造成流对象无法关闭从而造成内存不足?
2、如果createPdf()方法引发异常的时候会不会造成流对象无法关闭从而造成内存不足?
我也非常清楚这样的写法不可取,最起码应该在finally块中释放使用的流,有可能是由于项目组开发初期io流操作知识欠缺,造成项目中大量的代码都是这样实现的,希望能够指点迷津,代码量太大,而且时间比较紧,如果内存会被自动回收,那么当前暂时就不对这块做改动。
Map<String,BufferedInputStream> map = new HashMap<String,new BufferedInputStream>();
map.put("a",new BufferedInputStream(new ByteArrayInputStream(byteGz)));
...
之后的逻辑会调用void createPdf(Map<String,BufferedInputStream> map)方法生成pdf文件存放到数据库中,BufferedInputStream流对象由于没有任何指向,因此始终没有代码实现流的关闭。
请问:
1、这种代码实现的方式会不会造成流对象无法关闭从而造成内存不足?
2、如果createPdf()方法引发异常的时候会不会造成流对象无法关闭从而造成内存不足?
我也非常清楚这样的写法不可取,最起码应该在finally块中释放使用的流,有可能是由于项目组开发初期io流操作知识欠缺,造成项目中大量的代码都是这样实现的,希望能够指点迷津,代码量太大,而且时间比较紧,如果内存会被自动回收,那么当前暂时就不对这块做改动。
解决方案 »
- 直接运行jar文件出错,Cannot find the main class……求教
- 【小测试2】写出此代码的执行结果,并解释原因
- JTable上显示JCheckBox,如何显示disabled
- 怎么从今年的多少天推算出这一天的日期?或怎么从星期数得到这一星期的范围?
- 第一次用eclipse(WTP all in one)按照eclipse网站上的教程写程序却无法编译!郁闷中!
- 可运行jar的问题
- 点击“esc”后自动关闭窗口(窗口里有jTextField控件的)
- 求解:如何在JAVA中实现简单的的公式运算?
- 那位提供一个低版本cvsnt的下载地址?
- 求教applet执行问题
- 线程问题
- oracel安装时出现的错误
不过 JAVA有自动回收机制 也就是说在回收之前,内存的容量不被占满应该没有问题。(但是JAVA的回收机制是相当不确定的。具有不稳定性,就是你不知道他什么时候会回收垃圾)
生成PDF放数据库是什么意思呢
由于生成的pdf不可任意复制或者下载,因此要把生成的pdf存入数据库的blob字段中
你也说了,如果异常了IO流会不会关闭?这个要搞好异常处理。finally里面去判断一把,做好资源回收。清空集合之前要关闭里面的IO流,再把集合清空
还有注意静态变量应当适时的、符合业务逻辑地置为null
原来做过一个东西 就是静态变量没有及时的置为null 导致GC无法回收
过多的占用内存
public static void main(String[] args) {
for(int i=0;i<100;i++){
//byte[] byteGz = new byte[1024*1024*1024];//1G
byte[] byteGz = new byte[1024];//1G
Map<String,BufferedInputStream> map = new HashMap<String,BufferedInputStream>();
map.put("a"+i,new BufferedInputStream(new ByteArrayInputStream(byteGz)));
}
}
问题不是出在流上,而是出在byte[]上面。
Map<String,BufferedInputStream> map = new HashMap<String,BufferedInputStream>();//一直持有引用不释放,导致内存无法释放
for(int i=0;i<100;i++){
byte[] byteGz = new byte[1024*1024*1024];//1G
//byte[] byteGz = new byte[1024];//1G
map.put("a"+i,new BufferedInputStream(new ByteArrayInputStream(byteGz)));
}
}
Map<String,BufferedInputStream> map = new HashMap<String,new BufferedInputStream>();流都是现用现打开的,然后及时关闭。
ByteArrayInputStream 虽然不用关,但是字节都存在内存中,不及时释放,服务器迟早会崩溃。要改的话,
一、把 byte[] byteGz = ..... 存到一个临时文件。
二、map.put(String, 临时文件路径)
如果,map 不好改,就在 new BufferedInputStream(new ByteArrayInputStream(byteGz)) 中,自己实现一个流 代替 ByteArrayInputStream,流只保存临时文件的路径。读数据的时候,现生成一个FileInputStream去读数据。
请问像我现在这样的逻辑
map.put("a",new BufferedInputStream(new ByteArrayInputStream(byteGz)));
...
在void createPdf(Map<String,BufferedInputStream> map)方法中,可否只关闭BufferedInputStream?ByteArrayInputStream是否可以在关闭BufferedInputStream后关闭呢?
Map<String,BufferedInputStream> map = new HashMap<String,BufferedInputStream>();
for(int i=0;i<10000;i++){
byte[] byteGz = new byte[1024*1024];//
map.put("a"+i,new BufferedInputStream(new ByteArrayInputStream(byteGz)));
}
}运行这段代码必造成内存溢出。而改成这样后,就没有问题:public static void main(String[] args){
Map<String,BufferedInputStream> map = new HashMap<String,BufferedInputStream>();
for(int i=0;i<10000;i++){
byte[] byteGz = new byte[1024*1024];//
map.put("a"+i,new BufferedInputStream(new ByteArrayInputStream(byteGz)));
BufferedInputStream get = map.get("a" + i);
try {
get.close();
} catch (IOException ex) {
Logger.getLogger(ImageTest.class.getName()).log(Level.SEVERE, null, ex);
}
}
}这说明BufferedInputStream释放了里面的ByteArrayInputStream也自动释放了,所有拟把BufferedInputStream释放了就行了