Jvm org.apache.commons.io.FileCleaningTracker不会删除临时文件,除非显式调用System.gc()?
我正在为我的web应用程序开发一个上传图像功能,并且在apache commons fileupload的“FileCleaningTracker”中遇到了一个奇怪的问题。我有一个带有实例变量FileCleaningTracker的ImageUploadService,然后我有一个upload方法,该方法创建DiskFileItemFactory的实例,然后引用FileCleaningTracker,在upload方法成功完成后,我将DiskFileItemFactory的FileCleaningTracker设置为null,因此,我希望对DiskFileItemFactory进行垃圾收集,然后会通知FileCleaningTracker中PhantomReference的底层子类,从而删除DiskFileItemFactory创建的临时文件 但是,直到我将DiskFileItemFactory设置为null并在upload方法结束时调用System.gc()(仅将DiskFileItemFactory设置为null没有帮助),这种情况才会发生。这对我来说似乎很奇怪。这是我的密码:Jvm org.apache.commons.io.FileCleaningTracker不会删除临时文件,除非显式调用System.gc()?,jvm,Jvm,我正在为我的web应用程序开发一个上传图像功能,并且在apache commons fileupload的“FileCleaningTracker”中遇到了一个奇怪的问题。我有一个带有实例变量FileCleaningTracker的ImageUploadService,然后我有一个upload方法,该方法创建DiskFileItemFactory的实例,然后引用FileCleaningTracker,在upload方法成功完成后,我将DiskFileItemFactory的FileCleanin
@Override
public void upload(final HttpServletRequest request) {
ValidateUtils.checkNotNull(request, "upload request");
final File tmp = new File(this.tempFolder);
if (!tmp.exists()) {
tmp.mkdir();
}
DiskFileItemFactory fileItemFactory = new DiskFileItemFactory(this.sizeThreshold, tmp);
fileItemFactory.setFileCleaningTracker(this.fileCleaningTracker);
ServletFileUpload uploadHandler = new ServletFileUpload(fileItemFactory);
List items;
try {
items = uploadHandler.parseRequest(request);
} catch (final FileUploadException e) {
throw new ImageUploadServiceException("Error parsing the http servlet request for image upload.", e);
}
final Iterator it = items.iterator();
while (it.hasNext()) {
final DiskFileItem item = (DiskFileItem) it.next();
if (item.isFormField()) {
// log message
} else {
final String fileName = item.getName();
final File destination = this.createFileForUpload(fileName, this.uploadFolder);
FileChannel outChannel;
try {
outChannel = new FileOutputStream(destination).getChannel();
} catch (final FileNotFoundException e) {
throw new ImageUploadServiceException(e);
}
FileChannel inChannel = null;
try {
inChannel = new FileInputStream(item.getStoreLocation()).getChannel();
outChannel.transferFrom(inChannel, 0, item.getSize());
} catch (final IOException e) {
throw new ImageUploadServiceException(String.format("Error uploading image to '%s/%s'.", this.uploadFolder, destination.getName()), e);
} finally {
IOUtils.closeChannel(inChannel);
IOUtils.closeChannel(outChannel);
}
}
}
fileItemFactory.setFileCleaningTracker(null);
}
上面的代码导致每次上载都会在临时文件夹中创建一个文件,但不会在最后由“fileCleaningTracker”将其删除,这可能是因为DiskFileItemFactory实例没有被垃圾收集(我不明白为什么不应该被垃圾收集),或者它已经被GCD,但没有被fileCleaningTracker中的PhantomReference通知(幻影参考有多可靠?)
我等了10分钟,文件还在,所以不应该是因为GC没有运行,也没有例外
现在,如果我添加以下代码,每次上传后都会删除临时文件:
fileItemFactory = null;
System.gc();
这对我来说很奇怪,因为我希望fileItemFactory在没有显式调用System.gc()的情况下被GCed
如有任何意见,将不胜感激
谢谢。我也有同样的问题。即使在服务器关闭后,临时文件也不会被删除:GC进程还没有启动,因此
文件清理tracker
没有机会从引用队列
中删除跟踪文件,所有文件都保留在硬盘上
由于我的应用程序的特定行为,每次上传后我都必须清理(文件可能非常大)。我没有使用标准的org.apache.commons.io.FileCleaningTracker
,我很幸运地用自己的实现覆盖了这个类:
/**
* Cleaning tracker to clean files after each upload with special method invocation.
* Not thread safe and must be used with 1 factory = 1 thread policy.
*/
public class DeleteFilesOnEndUploadCleaningTracker extends FileCleaningTracker {
private List<String> filesToDelete = new ArrayList();
public void deleteTemporaryFiles() {
for (String file : filesToDelete) {
new File(file).delete();
}
filesToDelete.clear();
}
@Override
public synchronized void exitWhenFinished() {
deleteTemporaryFiles();
}
@Override
public int getTrackCount() {
return filesToDelete.size();
}
@Override
public void track(File file, Object marker) {
filesToDelete.add(file.getAbsolutePath());
}
@Override
public void track(File file, Object marker, FileDeleteStrategy deleteStrategy) {
filesToDelete.add(file.getAbsolutePath());
}
@Override
public void track(String path, Object marker) {
filesToDelete.add(path);
}
@Override
public void track(String path, Object marker, FileDeleteStrategy deleteStrategy) {
filesToDelete.add(path);
}
}
在您完成上传项目的工作后,不要忘记调用清理方法:
tracker.deleteTemporaryFiles();
忘了提到:我使用commons文件上传version1.2.2和commons io
version1.3.2
tracker.deleteTemporaryFiles();