- 浏览: 258800 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
申1987:
收藏
Java解析XML文件 -
wangyu2010302660001:
发布成文本Service后,那个testclass就load不 ...
使用URLClassLoader动态加载类 -
joe_zhpf:
thanks 终于理解了..
android touch mode -
wander312:
嗯, 我试的OK.
android findViewById 返回null的问题 -
javetu_7:
你说的也不对,我试了,还是NULL
android findViewById 返回null的问题
由于需要做一个在线更新模块,需要在程序里对jar文件解压,测试程序如下
开始的测试程序如下:
发现确实可以解压,但被解压的jar文件一直被线程占用,不能删除,后来经javaworld版大指点发现问题:
红色部分,每次循环都生成一个input/output stream,但我在finally里(绿色)只处理了最后一个stream的close,导致之前的stream全部没有清除。
解决办法是加上xJarFile.close(),就可以了。
但是,新问题又来了,虽然被解压的jar包不被线程占用了,但是解出来的文件夹里的文件却被线程占用(解出来的文件),当用完后不能删除。最后怀疑是没有做垃圾回收导致的问题所以在finally里又加上System.gc()这个方法。但这个方法只是标明可以进行垃圾回收,到底回收不回收却用jvm决定,所以并不知道是否安全。
最后发现使用JarFile.close()并不能关闭输出流 doc上写的是“将关闭以前调用 getInputStream 方法返回的所有输入流。”,输出流还是需要手动清除,System.gc()其实就是代替你清除这些没有回收的内存,为了安全起见改成手动.
开始的测试程序如下:
package test; import java.io.BufferedInputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.util.Enumeration; import java.util.jar.*; public class TestJarFile extends Thread { /** * @param args */ public TestJarFile(){ run(); } public void UnJarFile(){ JarFile xJarFile = null; JarEntry xJarEntry; Enumeration<JarEntry> enumer; BufferedInputStream is = null; FileOutputStream fos = null; byte data[] = new byte[1024]; try { xJarFile=new JarFile("d:/TestJar.jar"); if(xJarFile.size()==0) return; enumer=xJarFile.entries(); [color=red] while(enumer.hasMoreElements()){ xJarEntry= enumer.nextElement(); if(xJarEntry.isDirectory()){ //event continue; } is=new BufferedInputStream(xJarFile.getInputStream(xJarEntry)); System.out.println(xJarEntry.getName()); if(xJarEntry.getName().contains(".MF")) continue; fos =new FileOutputStream("D:/TestJar/"+xJarEntry.getName()); int len=0; [/color] while((len=is.read(data))!=-1){ fos.write(data,0,len); } } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally{ try{ [color=greens] fos.flush(); fos.close(); is.close(); [/color] } catch(Exception e){ } } } public static void main(String[] args) { TestJarFile t=new TestJarFile(); } public void run(){ File xDir=new File("D:/TestJar/"); long count=9999999l; while(true){ try { sleep(1500); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } File xFiles[]=xDir.listFiles(); System.out.println(xFiles.length); if(xFiles.length==0){ UnJarFile(); } } } }
发现确实可以解压,但被解压的jar文件一直被线程占用,不能删除,后来经javaworld版大指点发现问题:
红色部分,每次循环都生成一个input/output stream,但我在finally里(绿色)只处理了最后一个stream的close,导致之前的stream全部没有清除。
解决办法是加上xJarFile.close(),就可以了。
但是,新问题又来了,虽然被解压的jar包不被线程占用了,但是解出来的文件夹里的文件却被线程占用(解出来的文件),当用完后不能删除。最后怀疑是没有做垃圾回收导致的问题所以在finally里又加上System.gc()这个方法。但这个方法只是标明可以进行垃圾回收,到底回收不回收却用jvm决定,所以并不知道是否安全。
最后发现使用JarFile.close()并不能关闭输出流 doc上写的是“将关闭以前调用 getInputStream 方法返回的所有输入流。”,输出流还是需要手动清除,System.gc()其实就是代替你清除这些没有回收的内存,为了安全起见改成手动.
package test; import java.io.BufferedInputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.util.Enumeration; import java.util.jar.*; public class TestJarFile extends Thread { /** * @param args */ public TestJarFile(){ run(); } public void UnJarFile(){ JarFile xJarFile = null; JarEntry xJarEntry; Enumeration<JarEntry> enumer; BufferedInputStream is = null; FileOutputStream fos = null; byte data[] = new byte[1024]; try { xJarFile=new JarFile("d:/TestJar.jar"); if(xJarFile.size()==0) return; enumer=xJarFile.entries(); while(enumer.hasMoreElements()){ xJarEntry= enumer.nextElement(); if(xJarEntry.isDirectory()) continue; is=new BufferedInputStream(xJarFile.getInputStream(xJarEntry)); System.out.println(xJarEntry.getName()); if(xJarEntry.getName().contains(".MF")) continue; fos =new FileOutputStream("D:/TestJar/"+xJarEntry.getName()); int len=0; while((len=is.read(data))!=-1){ fos.write(data,0,len); } fos.flush(); fos.close(); fos=null; } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally{ try{ fos.flush(); fos.close(); xJarFile.close(); is.close(); // System.gc(); } catch(Exception e){ } } } public static void main(String[] args) { TestJarFile t=new TestJarFile(); } public void run(){ File xDir=new File("D:/TestJar/"); while(true){ try { sleep(1500); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } File xFiles[]=xDir.listFiles(); System.out.println(xFiles.length); if(xFiles.length==0){ UnJarFile(); } } } } 在第一个while循环里当用完output stream后就立刻清空。最后问题的症结还是在于outputstream的对象没有释放导致的问题发生
发表评论
-
区别在于内存分配的方式,allocate分配的内存在jvm管理范围内,directAllocate分配的内存则不是由jvm管理,可以理解成是类似 C++那种分配
2010-05-25 11:15 1554区别在于内存分配的方式,allocate分配的内存在jvm管理 ... -
java中ArrayList 、LinkList区别
2010-05-25 11:02 165221.ArrayList是实现了基于动态数组的数据结 ... -
谈谈Unicode编码,简要解释UCS、UTF、BMP、BOM等名词
2010-05-20 15:24 1156这是一篇程序员写 ... -
HashCode的作用
2010-05-18 14:09 5262首先,想要明白hashCode ... -
hashTable与HashMap区别
2010-05-07 09:50 1577HashTable的应用非常广泛, HashMap ... -
java String详解
2010-01-15 11:11 2695Java字符串类(java.lang.String)是Jav ... -
java 读xml
2009-12-25 16:05 870DocumentBuilderFactory factory ... -
抽象类实现接口,可以不实现其中的抽象方法
2009-12-03 13:20 1981抽象类实现接口,可以不实现其中的抽象方法,而将抽象方法的实现交 ... -
linux命令grep
2009-07-08 11:24 1431grep "key" xxx.log时输出 ... -
子类覆盖问题的解释
2009-07-07 16:31 1009如果子类没有重写父类的方法,调用父类的方法的时候,实际上是去父 ... -
关于字符集转换的本质问题。
2009-03-13 15:36 1461UTF-8 UTF-16BE UTF-16LE GB2312 ... -
java.lang.class类入门的介绍
2008-10-17 15:05 1449前言:Java的类库日益庞大,所包含的类和接口也不计其数。但其 ... -
内部类的介绍
2008-10-14 10:52 939提起Java内部类(Inner Class)可能很多人不太熟悉 ... -
java.io中的设计模式
2008-08-19 14:18 1557我想任何一本介绍模式的书在讲到Decorator模式的 ... -
使用Graphics2D画虚线和设置线的宽度
2008-07-31 15:50 11717public void paint(Graphics ... -
java变量基础
2008-07-30 10:35 1285变量 变量是指? 变量是存放 ... -
reader和stream的区别
2008-07-24 10:47 3018java.io.Reader 和 java.io.InputS ... -
111
2008-07-10 20:01 874hang out with: spend time with -
多线程的一些问题
2008-07-08 14:35 1064Java的线程编程非常简单。但有时会看到一些关于线程的错误用 ... -
Javax.comm串口通讯类简介
2008-07-08 13:33 4193Javax.comm简介 Javax.comm是Sun ...
相关推荐
zxing/zxing-j2se-1.7.jar包, 包含类 com.google.zxing.StringsResourceTranslator.class com.google.zxing.client.j2se.BufferedImageLuminanceSource.class ...
J2SE6.0.chm api
J2SE1.6.chm 官方帮助文档,chm格式,使用更加方便
j2se6.chm.zip
使用maven在引入zxing这个包的时候,经常引不到这个包,这里提供下载。
javase基础
jar包,官方版本,自测可用
j2se6.part3.chm 英文版的非中文版
j2se6.part1,chm格式,英文版的
[Java参考文档].J2SE6.0_CN.CHM,由于文件过大,所以划分了两个rar文件
JAVA参考大全.J2SE
J2SE应用编程Java IDL实例代码J2SE application programming code in Java IDL Example
自学java必备资源,高级教师推荐,欢迎下载!
com.google.zxing.client.j2se.BufferedImageLuminanceSource和com.google.zxing.client.j2se.MatrixToImageWriter,亲测可用
这是在 sun java jdk 1.4.2 平台上开发的一个类库文件,解决上传文件到 java web server 的问题。 和最早的版本相比,该版本修正了当 request.getgetCharacterEncoding() 为 null 时所导致的 NullException 。
JAVA参考大全.J2SE.5EDITION
qrcode zxing 二维码生成解析,代码齐全。 ... import com.google.zxing.client.j2se.BufferedImageLuminanceSource; ... ...import com.swetake.util.Qrcode;...import java.util.HashMap; import java.util.Map;
j2se6.chm+JDK_API_1.6_zh_中文.CHM+jdk_api_1.7.chm Java程序员必备工具
JAVA参考大全.J2SE.5EDITION.part7.rar