慢慢的循环MD5计算时出现内存泄漏

时间:2013-08-21 00:06:11

标签: java performance memory garbage-collection md5

我在这里问了一个类似的问题Performance issues when looping an MD5 calculator on many files,但我意识到问题不是代码,而是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();

}

1 个答案:

答案 0 :(得分:0)

你的MD5对象正在不断增长,因为你永远不会重置它,正如@BevynQ所观察到的那样,并且你的代码不是线程安全的。您必须使用方法本地MD5ByteBuffer对象。使用更大的ByteBuffer,例如32k或更多,以使其更快。

您无需同时关闭RandomAccessFile FileChannel:您可以这样做。