循环MD5计算时缓慢和内存泄漏



我在这里问了一个类似的问题在许多文件上循环MD5计算器时会出现性能问题,但我意识到问题不在于代码,而在于GC,所以我需要一个新的页面来解决同样的问题,但要有不同的解决方案。

我正在对1000多个图像文件运行MD5计算循环。该程序在大约200之后运行缓慢,并且使用大量内存(空闲->不活动)。它使用了我启动时可用的内存(2GB-5GB)。

我试着使用Java.io/FastMD5。这段代码是Java.nio的最新测试。所有这些都出现了问题,甚至FastMD5,这是一个外部库,所以问题显然不是我计算MD5的方式。

问题似乎是代码运行得太快,GC没有时间跟上对象。

是否对GC或我的代码进行了任何优化,可以帮助我解决内存问题

编辑尝试使用ThreadLocal。不行。我意识到这个程序以某种方式缓存MD5,因为在一个缓慢的循环(有内存泄漏)之后,会出现一个没有内存泄漏的快速循环。释放内存后,程序再次变慢(然后变快)。

public static void main(String[] args) {
        File[] directory = new File("/Users/itaihay/Desktop/Library/Seattle 2010").listFiles();
    for(int i = 0; i < directory.length;i++){
        System.out.println(Utils.toMD5(directory[i]));
        }
}

Utils.toMD5():

  public class Utils {

public static final ThreadLocal<MessageDigest> mdT = new ThreadLocal<MessageDigest>(){
   protected MessageDigest initialValue(){
        try {
            return MessageDigest.getInstance("MD5");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();  
        }
       return null;
   }
};
public static final ThreadLocal<ByteBuffer> bufferT = new ThreadLocal<ByteBuffer>(){
    protected ByteBuffer initialValue(){
            return ByteBuffer.allocate(32000);
    }
};
private static Utils util = new Utils();
private static MessageDigest md;
private static FileChannel fileChannel;
private static ByteBuffer buffer = bufferT.get();
private Utils() {
//            md = MessageDigest.getInstance("MD5");
        md = mdT.get();
}
public static String toMD5(File file) throws NoSuchAlgorithmException, IOException {
//        BufferedInputStream fis = new BufferedInputStream(new FileInputStream(file));
   RandomAccessFile randomAccessFile = new RandomAccessFile(file, "r");
    fileChannel = randomAccessFile.getChannel();
    /*while (fileChannel.read(buffer) != -1) {
        buffer.flip();
        md.update(buffer);
        buffer.clear();
    }*/
    while (fileChannel.read(bufferT.get()) != -1) {
        bufferT.get().flip();
        md.update(bufferT.get());
        bufferT.get().clear();
    }
    byte[] mdbytes = md.digest();
    randomAccessFile.close();
    bufferT.get().clear();
    mdT.get().reset();
    return javax.xml.bind.DatatypeConverter.printHexBinary(mdbytes)
            .toLowerCase();
}

正如@BevynQ所观察到的,您的MD5对象正在无限制地增长,因为您从未重置过它,同样,您的代码也不是线程安全的。必须使用方法本地MD5ByteBuffer对象。使用更大的ByteBuffer,例如32k或更大,使其运行速度更快。

您不需要同时关闭RandomAccessFileFileChannel:一个就可以了。

最新更新