由于需要做一个在线更新模块,需要在程序里对jar文件解压,测试程序如下
开始的测试程序如下:
发现确实可以解压,但被解压的jar文件一直被线程占用,不能删除,后来经javaworld版大指点发现问题:
红色部分,每次循环都生成一个input/output stream,但我在finally里(绿色)只处理了最后一个stream的close,导致之前的stream全部没有清除。
解决办法是加上xJarFile.close(),就可以了。
但是,新问题又来了,虽然被解压的jar包不被线程占用了,但是解出来的文件夹里的文件却被线程占用(解出来的文件),当用完后不能删除。最后怀疑是没有做垃圾回收导致的问题所以在finally里又加上System.gc()这个方法。但这个方法只是标明可以进行垃圾回收,到底回收不回收却用jvm决定,所以并不知道是否安全。
最后发现使用JarFile.close()并不能关闭输出流 doc上写的是“将关闭以前调用 getInputStream 方法返回的所有输入流。”,输出流还是需要手动清除,System.gc()其实就是代替你清除这些没有回收的内存,为了安全起见改成手动.
[code]
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的对象没有释放导致的问题发生
[/code]
开始的测试程序如下:
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()其实就是代替你清除这些没有回收的内存,为了安全起见改成手动.
[code]
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的对象没有释放导致的问题发生
[/code]