在做性能测试的时候,发现一个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.         }