在做性能测试的时候,发现一个MD5的工具类有问题,在大压力的情况下,会出现计算出错的问题,分析了一下代码,找到了原因所在。

这是原来的代码:

 

  1. public class MD5 { 
  2.  
  3.     // ------------------------------------------------------------ Private data 
  4.     private static SecureRandom random = null
  5.     private static MessageDigest md    = null
  6.  
  7.     // ------------------------------------------------------------ Constructors 
  8.  
  9.     /** Creates a new instance of MD5 */ 
  10.     protected MD5() { 
  11.     } 
  12.  
  13.     // ---------------------------------------------------------- Public methods 
  14.  
  15.     /** 
  16.      * Returns a new nonce to be used for MD5 authentication. The nonce bytes 
  17.      * are guaranteed to be in the printable range from ascii 32 to 128. 
  18.      * 
  19.      * @return a new 16 bytes long nonce 
  20.      */ 
  21.     public static byte[] getNextNonce() { 
  22.         byte[] nextNonce = new byte[16]; 
  23.         random.nextBytes(nextNonce); 
  24.  
  25.         int i; 
  26.         for (int j=0; j<nextNonce.length; ++j) { 
  27.             i = nextNonce[j] & 0x000000ff
  28.             if ((i<32) || (i>128)) { 
  29.                 nextNonce[j] = (byte)(32 + (i % 64)); 
  30.             } 
  31.         } 
  32.  
  33.         return nextNonce; 
  34.     } 
  35.  
  36.     /** 
  37.      * MD5ies the given content 
  38.      * 
  39.      * @param data the data to be digested 
  40.      * 
  41.      */ 
  42.     public static byte[] digest(byte[] data) { 
  43.         md.reset(); 
  44.         return md.digest(data); 
  45.     } 
  46.  
  47.     // --------------------------------------------------------- Private methods 
  48.  
  49.     /** 
  50.      * Creates and initialize the random generator. Called ad class loading 
  51.      * time. 
  52.      */ 
  53.     private static void randomGeneratorInit() 
  54.     throws java.security.NoSuchAlgorithmException { 
  55.         random = SecureRandom.getInstance("SHA1PRNG"); 
  56.     } 
  57.  
  58.     // ------------------------------------------------------------- Static code 
  59.  
  60.     static { 
  61.         try { 
  62.             randomGeneratorInit(); 
  63.             md = MessageDigest.getInstance("MD5"); 
  64.         } catch(Exception e) { 
  65.             e.printStackTrace(); 
  66.         } 
  67.     } 

  68. 这是我修改后的代码:
  69.  
  1. public class MD5 { 
  2.  
  3.     // ------------------------------------------------------------ Private data 
  4.     private static SecureRandom random = null
  5.     private static MessageDigest md    = null
  6.  
  7.     // ------------------------------------------------------------ Constructors 
  8.  
  9.     /** Creates a new instance of MD5 */ 
  10.     protected MD5() { 
  11.     } 
  12.  
  13.     // ---------------------------------------------------------- Public methods 
  14.  
  15.     /** 
  16.      * Returns a new nonce to be used for MD5 authentication. The nonce bytes 
  17.      * are guaranteed to be in the printable range from ascii 32 to 128. 
  18.      * 
  19.      * @return a new 16 bytes long nonce 
  20.      */ 
  21.     public static byte[] getNextNonce() { 
  22.         byte[] nextNonce = new byte[16]; 
  23.         random.nextBytes(nextNonce); 
  24.  
  25.         int i; 
  26.         for (int j=0; j<nextNonce.length; ++j) { 
  27.             i = nextNonce[j] & 0x000000ff; 
  28.             if ((i<32) || (i>128)) { 
  29.                 nextNonce[j] = (byte)(32 + (i % 64)); 
  30.             } 
  31.         } 
  32.  
  33.         return nextNonce; 
  34.     } 
  35.  
  36.     /** 
  37.      * MD5ies the given content 
  38.      * 
  39.      * @param data the data to be digested 
  40.      * 
  41.      */ 
  42.     public static byte[] digest(byte[] data) { 
  43.         synchronized (md) { 
  44.             md.reset(); 
  45.             return md.digest(data); 
  46.         } 
  47.  
  48.     } 
  49.  
  50.     // --------------------------------------------------------- Private methods 
  51.  
  52.     /** 
  53.      * Creates and initialize the random generator. Called ad class loading 
  54.      * time. 
  55.      */ 
  56.     private static void randomGeneratorInit() 
  57.     throws java.security.NoSuchAlgorithmException { 
  58.         random = SecureRandom.getInstance("SHA1PRNG"); 
  59.     } 
  60.  
  61.     // ------------------------------------------------------------- Static code 
  62.  
  63.     static { 
  64.         try { 
  65.             randomGeneratorInit(); 
  66.             md = MessageDigest.getInstance("MD5"); 
  67.         } catch(Exception e) { 
  68.             e.printStackTrace(); 
  69.         } 
  70.     } 

主要区别在这里:

  1. synchronized (md) { 
  2.             md.reset(); 
  3.             return md.digest(data); 
  4.         }