6321472: Add CRC-32C API
authorsherman
Fri, 21 Nov 2014 09:28:53 -0800
changeset 27737 0a3fb0529425
parent 27736 8c9bd4be4a86
child 27746 67a41aa6d29a
6321472: Add CRC-32C API Summary: to add CRC-32C api and implementation Reviewed-by: sherman Contributed-by: staffan.friberg@oracle.com
jdk/src/java.base/share/classes/java/util/zip/Adler32.java
jdk/src/java.base/share/classes/java/util/zip/CRC32.java
jdk/src/java.base/share/classes/java/util/zip/CRC32C.java
jdk/src/java.base/share/classes/java/util/zip/Checksum.java
jdk/src/java.base/share/classes/java/util/zip/package-info.java
jdk/src/java.base/share/classes/java/util/zip/package.html
jdk/test/java/util/zip/ChecksumBase.java
jdk/test/java/util/zip/TestCRC32.java
jdk/test/java/util/zip/TestCRC32C.java
jdk/test/java/util/zip/TestChecksum.java
--- a/jdk/src/java.base/share/classes/java/util/zip/Adler32.java	Fri Nov 21 16:05:11 2014 +0100
+++ b/jdk/src/java.base/share/classes/java/util/zip/Adler32.java	Fri Nov 21 09:28:53 2014 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -34,9 +34,8 @@
  * can be computed much faster.
  *
  * <p> Passing a {@code null} argument to a method in this class will cause
- * a {@link NullPointerException} to be thrown.
+ * a {@link NullPointerException} to be thrown.</p>
  *
- * @see         Checksum
  * @author      David Connelly
  */
 public
@@ -53,9 +52,8 @@
     /**
      * Updates the checksum with the specified byte (the low eight
      * bits of the argument b).
-     *
-     * @param b the byte to update the checksum with
      */
+    @Override
     public void update(int b) {
         adler = update(adler, b);
     }
@@ -63,11 +61,12 @@
     /**
      * Updates the checksum with the specified array of bytes.
      *
-     * @throws  ArrayIndexOutOfBoundsException
-     *          if {@code off} is negative, or {@code len} is negative,
-     *          or {@code off+len} is greater than the length of the
-     *          array {@code b}
+     * @throws ArrayIndexOutOfBoundsException
+     *         if {@code off} is negative, or {@code len} is negative, or
+     *         {@code off+len} is negative or greater than the length of
+     *         the array {@code b}.
      */
+    @Override
     public void update(byte[] b, int off, int len) {
         if (b == null) {
             throw new NullPointerException();
@@ -79,28 +78,15 @@
     }
 
     /**
-     * Updates the checksum with the specified array of bytes.
-     *
-     * @param b the byte array to update the checksum with
-     */
-    public void update(byte[] b) {
-        adler = updateBytes(adler, b, 0, b.length);
-    }
-
-
-    /**
      * Updates the checksum with the bytes from the specified buffer.
      *
-     * The checksum is updated using
-     * buffer.{@link java.nio.Buffer#remaining() remaining()}
-     * bytes starting at
-     * buffer.{@link java.nio.Buffer#position() position()}
-     * Upon return, the buffer's position will be updated to its
-     * limit; its limit will not have been changed.
+     * The checksum is updated with the remaining bytes in the buffer, starting
+     * at the buffer's position. Upon return, the buffer's position will be
+     * updated to its limit; its limit will not have been changed.
      *
-     * @param buffer the ByteBuffer to update the checksum with
      * @since 1.8
      */
+    @Override
     public void update(ByteBuffer buffer) {
         int pos = buffer.position();
         int limit = buffer.limit();
@@ -113,9 +99,12 @@
         } else if (buffer.hasArray()) {
             adler = updateBytes(adler, buffer.array(), pos + buffer.arrayOffset(), rem);
         } else {
-            byte[] b = new byte[rem];
-            buffer.get(b);
-            adler = updateBytes(adler, b, 0, b.length);
+            byte[] b = new byte[Math.min(buffer.remaining(), 4096)];
+            while (buffer.hasRemaining()) {
+                int length = Math.min(buffer.remaining(), b.length);
+                buffer.get(b, 0, length);
+                update(b, 0, length);
+            }
         }
         buffer.position(limit);
     }
@@ -123,6 +112,7 @@
     /**
      * Resets the checksum to initial value.
      */
+    @Override
     public void reset() {
         adler = 1;
     }
@@ -130,6 +120,7 @@
     /**
      * Returns the checksum value.
      */
+    @Override
     public long getValue() {
         return (long)adler & 0xffffffffL;
     }
--- a/jdk/src/java.base/share/classes/java/util/zip/CRC32.java	Fri Nov 21 16:05:11 2014 +0100
+++ b/jdk/src/java.base/share/classes/java/util/zip/CRC32.java	Fri Nov 21 09:28:53 2014 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -32,9 +32,8 @@
  * A class that can be used to compute the CRC-32 of a data stream.
  *
  * <p> Passing a {@code null} argument to a method in this class will cause
- * a {@link NullPointerException} to be thrown.
+ * a {@link NullPointerException} to be thrown.</p>
  *
- * @see         Checksum
  * @author      David Connelly
  */
 public
@@ -51,9 +50,8 @@
     /**
      * Updates the CRC-32 checksum with the specified byte (the low
      * eight bits of the argument b).
-     *
-     * @param b the byte to update the checksum with
      */
+    @Override
     public void update(int b) {
         crc = update(crc, b);
     }
@@ -61,11 +59,12 @@
     /**
      * Updates the CRC-32 checksum with the specified array of bytes.
      *
-     * @throws  ArrayIndexOutOfBoundsException
-     *          if {@code off} is negative, or {@code len} is negative,
-     *          or {@code off+len} is greater than the length of the
-     *          array {@code b}
+     * @throws ArrayIndexOutOfBoundsException
+     *         if {@code off} is negative, or {@code len} is negative, or
+     *         {@code off+len} is negative or greater than the length of
+     *         the array {@code b}.
      */
+    @Override
     public void update(byte[] b, int off, int len) {
         if (b == null) {
             throw new NullPointerException();
@@ -77,27 +76,15 @@
     }
 
     /**
-     * Updates the CRC-32 checksum with the specified array of bytes.
+     * Updates the CRC-32 checksum with the bytes from the specified buffer.
      *
-     * @param b the array of bytes to update the checksum with
-     */
-    public void update(byte[] b) {
-        crc = updateBytes(crc, b, 0, b.length);
-    }
-
-    /**
-     * Updates the checksum with the bytes from the specified buffer.
+     * The checksum is updated with the remaining bytes in the buffer, starting
+     * at the buffer's position. Upon return, the buffer's position will be
+     * updated to its limit; its limit will not have been changed.
      *
-     * The checksum is updated using
-     * buffer.{@link java.nio.Buffer#remaining() remaining()}
-     * bytes starting at
-     * buffer.{@link java.nio.Buffer#position() position()}
-     * Upon return, the buffer's position will
-     * be updated to its limit; its limit will not have been changed.
-     *
-     * @param buffer the ByteBuffer to update the checksum with
      * @since 1.8
      */
+    @Override
     public void update(ByteBuffer buffer) {
         int pos = buffer.position();
         int limit = buffer.limit();
@@ -110,9 +97,12 @@
         } else if (buffer.hasArray()) {
             crc = updateBytes(crc, buffer.array(), pos + buffer.arrayOffset(), rem);
         } else {
-            byte[] b = new byte[rem];
-            buffer.get(b);
-            crc = updateBytes(crc, b, 0, b.length);
+            byte[] b = new byte[Math.min(buffer.remaining(), 4096)];
+            while (buffer.hasRemaining()) {
+                int length = Math.min(buffer.remaining(), b.length);
+                buffer.get(b, 0, length);
+                update(b, 0, length);
+            }
         }
         buffer.position(limit);
     }
@@ -120,6 +110,7 @@
     /**
      * Resets CRC-32 to initial value.
      */
+    @Override
     public void reset() {
         crc = 0;
     }
@@ -127,6 +118,7 @@
     /**
      * Returns CRC-32 value.
      */
+    @Override
     public long getValue() {
         return (long)crc & 0xffffffffL;
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/java/util/zip/CRC32C.java	Fri Nov 21 09:28:53 2014 -0800
@@ -0,0 +1,339 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.util.zip;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import sun.misc.Unsafe;
+import sun.nio.ch.DirectBuffer;
+
+/**
+ * A class that can be used to compute the CRC-32C of a data stream.
+ *
+ * <p>
+ * CRC-32C is defined in <a href="http://www.ietf.org/rfc/rfc3720.txt">RFC
+ * 3720</a>: Internet Small Computer Systems Interface (iSCSI).
+ * </p>
+ *
+ * <p>
+ * Passing a {@code null} argument to a method in this class will cause a
+ * {@link NullPointerException} to be thrown.
+ * </p>
+ *
+ * @since 1.9
+ */
+public final class CRC32C implements Checksum {
+
+    /*
+     * This CRC-32C implementation uses the 'slicing-by-8' algorithm described
+     * in the paper "A Systematic Approach to Building High Performance
+     * Software-Based CRC Generators" by Michael E. Kounavis and Frank L. Berry,
+     * Intel Research and Development
+     */
+
+    /**
+     * CRC-32C Polynomial
+     */
+    private static final int CRC32C_POLY = 0x1EDC6F41;
+    private static final int REVERSED_CRC32C_POLY = Integer.reverse(CRC32C_POLY);
+
+    private static final Unsafe UNSAFE = Unsafe.getUnsafe();
+
+    // Lookup tables
+    // Lookup table for single byte calculations
+    private static final int[] byteTable;
+    // Lookup tables for bulk operations in 'slicing-by-8' algorithm
+    private static final int[][] byteTables = new int[8][256];
+    private static final int[] byteTable0 = byteTables[0];
+    private static final int[] byteTable1 = byteTables[1];
+    private static final int[] byteTable2 = byteTables[2];
+    private static final int[] byteTable3 = byteTables[3];
+    private static final int[] byteTable4 = byteTables[4];
+    private static final int[] byteTable5 = byteTables[5];
+    private static final int[] byteTable6 = byteTables[6];
+    private static final int[] byteTable7 = byteTables[7];
+
+    static {
+        // Generate lookup tables
+        // High-order polynomial term stored in LSB of r.
+        for (int index = 0; index < byteTables[0].length; index++) {
+           int r = index;
+            for (int i = 0; i < Byte.SIZE; i++) {
+                if ((r & 1) != 0) {
+                    r = (r >>> 1) ^ REVERSED_CRC32C_POLY;
+                } else {
+                    r >>>= 1;
+                }
+            }
+            byteTables[0][index] = r;
+        }
+
+        for (int index = 0; index < byteTables[0].length; index++) {
+            int r = byteTables[0][index];
+
+            for (int k = 1; k < byteTables.length; k++) {
+                r = byteTables[0][r & 0xFF] ^ (r >>> 8);
+                byteTables[k][index] = r;
+            }
+        }
+
+        if (ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN) {
+            byteTable = byteTables[0];
+        } else { // ByteOrder.BIG_ENDIAN
+            byteTable = new int[byteTable0.length];
+            System.arraycopy(byteTable0, 0, byteTable, 0, byteTable0.length);
+            for (int[] table : byteTables) {
+                for (int index = 0; index < table.length; index++) {
+                    table[index] = Integer.reverseBytes(table[index]);
+                }
+            }
+        }
+    }
+
+    /**
+     * Calculated CRC-32C value
+     */
+    private int crc = 0xFFFFFFFF;
+
+    /**
+     * Creates a new CRC32C object.
+     */
+    public CRC32C() {
+    }
+
+    /**
+     * Updates the CRC-32C checksum with the specified byte (the low eight bits
+     * of the argument b).
+     */
+    @Override
+    public void update(int b) {
+        crc = (crc >>> 8) ^ byteTable[(crc ^ (b & 0xFF)) & 0xFF];
+    }
+
+    /**
+     * Updates the CRC-32C checksum with the specified array of bytes.
+     *
+     * @throws ArrayIndexOutOfBoundsException
+     *         if {@code off} is negative, or {@code len} is negative, or
+     *         {@code off+len} is negative or greater than the length of
+     *         the array {@code b}.
+     */
+    @Override
+    public void update(byte[] b, int off, int len) {
+        if (b == null) {
+            throw new NullPointerException();
+        }
+        if (off < 0 || len < 0 || off > b.length - len) {
+            throw new ArrayIndexOutOfBoundsException();
+        }
+        crc = updateBytes(crc, b, off, (off + len));
+    }
+
+    /**
+     * Updates the CRC-32C checksum with the bytes from the specified buffer.
+     *
+     * The checksum is updated with the remaining bytes in the buffer, starting
+     * at the buffer's position. Upon return, the buffer's position will be
+     * updated to its limit; its limit will not have been changed.
+     */
+    @Override
+    public void update(ByteBuffer buffer) {
+        int pos = buffer.position();
+        int limit = buffer.limit();
+        assert (pos <= limit);
+        int rem = limit - pos;
+        if (rem <= 0) {
+            return;
+        }
+
+        if (buffer instanceof DirectBuffer) {
+            crc = updateDirectByteBuffer(crc, ((DirectBuffer) buffer).address(),
+                                         pos, limit);
+        } else if (buffer.hasArray()) {
+            crc = updateBytes(crc, buffer.array(), pos + buffer.arrayOffset(),
+                              limit + buffer.arrayOffset());
+        } else {
+            byte[] b = new byte[Math.min(buffer.remaining(), 4096)];
+            while (buffer.hasRemaining()) {
+                int length = Math.min(buffer.remaining(), b.length);
+                buffer.get(b, 0, length);
+                update(b, 0, length);
+            }
+        }
+        buffer.position(limit);
+    }
+
+    /**
+     * Resets CRC-32C to initial value.
+     */
+    @Override
+    public void reset() {
+        crc = 0xFFFFFFFF;
+    }
+
+    /**
+     * Returns CRC-32C value.
+     */
+    @Override
+    public long getValue() {
+        return (~crc) & 0xFFFFFFFFL;
+    }
+
+    /**
+     * Updates the CRC-32C checksum with the specified array of bytes.
+     */
+    private static int updateBytes(int crc, byte[] b, int off, int end) {
+
+        // Do only byte reads for arrays so short they can't be aligned
+        // or if bytes are stored with a larger witdh than one byte.,%
+        if (end - off >= 8 && Unsafe.ARRAY_BYTE_INDEX_SCALE == 1) {
+
+            // align on 8 bytes
+            int alignLength
+                    = (8 - ((Unsafe.ARRAY_BYTE_BASE_OFFSET + off) & 0x7)) & 0x7;
+            for (int alignEnd = off + alignLength; off < alignEnd; off++) {
+                crc = (crc >>> 8) ^ byteTable[(crc ^ b[off]) & 0xFF];
+            }
+
+            if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN) {
+                crc = Integer.reverseBytes(crc);
+            }
+
+            // slicing-by-8
+            for (; off < (end - Long.BYTES); off += Long.BYTES) {
+                int firstHalf;
+                int secondHalf;
+                if (Unsafe.ADDRESS_SIZE == 4) {
+                    // On 32 bit platforms read two ints instead of a single 64bit long
+                    firstHalf = UNSAFE.getInt(b, Unsafe.ARRAY_BYTE_BASE_OFFSET + off);
+                    secondHalf = UNSAFE.getInt(b, Unsafe.ARRAY_BYTE_BASE_OFFSET + off
+                                               + Integer.BYTES);
+                } else {
+                    long value = UNSAFE.getLong(b, Unsafe.ARRAY_BYTE_BASE_OFFSET + off);
+                    if (ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN) {
+                        firstHalf = (int) value;
+                        secondHalf = (int) (value >>> 32);
+                    } else { // ByteOrder.BIG_ENDIAN
+                        firstHalf = (int) (value >>> 32);
+                        secondHalf = (int) value;
+                    }
+                }
+                crc ^= firstHalf;
+                if (ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN) {
+                    crc = byteTable7[crc & 0xFF]
+                            ^ byteTable6[(crc >>> 8) & 0xFF]
+                            ^ byteTable5[(crc >>> 16) & 0xFF]
+                            ^ byteTable4[crc >>> 24]
+                            ^ byteTable3[secondHalf & 0xFF]
+                            ^ byteTable2[(secondHalf >>> 8) & 0xFF]
+                            ^ byteTable1[(secondHalf >>> 16) & 0xFF]
+                            ^ byteTable0[secondHalf >>> 24];
+                } else { // ByteOrder.BIG_ENDIAN
+                    crc = byteTable0[secondHalf & 0xFF]
+                            ^ byteTable1[(secondHalf >>> 8) & 0xFF]
+                            ^ byteTable2[(secondHalf >>> 16) & 0xFF]
+                            ^ byteTable3[secondHalf >>> 24]
+                            ^ byteTable4[crc & 0xFF]
+                            ^ byteTable5[(crc >>> 8) & 0xFF]
+                            ^ byteTable6[(crc >>> 16) & 0xFF]
+                            ^ byteTable7[crc >>> 24];
+                }
+            }
+
+            if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN) {
+                crc = Integer.reverseBytes(crc);
+            }
+        }
+
+        // Tail
+        for (; off < end; off++) {
+            crc = (crc >>> 8) ^ byteTable[(crc ^ b[off]) & 0xFF];
+        }
+
+        return crc;
+    }
+
+    /**
+     * Updates the CRC-32C checksum reading from the specified address.
+     */
+    private static int updateDirectByteBuffer(int crc, long address,
+                                              int off, int end) {
+
+        // Do only byte reads for arrays so short they can't be aligned
+        if (end - off >= 8) {
+
+            // align on 8 bytes
+            int alignLength = (8 - (int) ((address + off) & 0x7)) & 0x7;
+            for (int alignEnd = off + alignLength; off < alignEnd; off++) {
+                crc = (crc >>> 8)
+                        ^ byteTable[(crc ^ UNSAFE.getByte(address + off)) & 0xFF];
+            }
+
+            if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN) {
+                crc = Integer.reverseBytes(crc);
+            }
+
+            // slicing-by-8
+            for (; off <= (end - Long.BYTES); off += Long.BYTES) {
+                // Always reading two ints as reading a long followed by
+                // shifting and casting was slower.
+                int firstHalf = UNSAFE.getInt(address + off);
+                int secondHalf = UNSAFE.getInt(address + off + Integer.BYTES);
+                crc ^= firstHalf;
+                if (ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN) {
+                    crc = byteTable7[crc & 0xFF]
+                            ^ byteTable6[(crc >>> 8) & 0xFF]
+                            ^ byteTable5[(crc >>> 16) & 0xFF]
+                            ^ byteTable4[crc >>> 24]
+                            ^ byteTable3[secondHalf & 0xFF]
+                            ^ byteTable2[(secondHalf >>> 8) & 0xFF]
+                            ^ byteTable1[(secondHalf >>> 16) & 0xFF]
+                            ^ byteTable0[secondHalf >>> 24];
+                } else { // ByteOrder.BIG_ENDIAN
+                    crc = byteTable0[secondHalf & 0xFF]
+                            ^ byteTable1[(secondHalf >>> 8) & 0xFF]
+                            ^ byteTable2[(secondHalf >>> 16) & 0xFF]
+                            ^ byteTable3[secondHalf >>> 24]
+                            ^ byteTable4[crc & 0xFF]
+                            ^ byteTable5[(crc >>> 8) & 0xFF]
+                            ^ byteTable6[(crc >>> 16) & 0xFF]
+                            ^ byteTable7[crc >>> 24];
+                }
+            }
+
+            if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN) {
+                crc = Integer.reverseBytes(crc);
+            }
+        }
+
+        // Tail
+        for (; off < end; off++) {
+            crc = (crc >>> 8)
+                    ^ byteTable[(crc ^ UNSAFE.getByte(address + off)) & 0xFF];
+        }
+
+        return crc;
+    }
+}
--- a/jdk/src/java.base/share/classes/java/util/zip/Checksum.java	Fri Nov 21 16:05:11 2014 +0100
+++ b/jdk/src/java.base/share/classes/java/util/zip/Checksum.java	Fri Nov 21 09:28:53 2014 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 1999, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,16 +22,17 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+package java.util.zip;
 
-package java.util.zip;
+import java.nio.ByteBuffer;
 
 /**
  * An interface representing a data checksum.
  *
- * @author      David Connelly
+ * @author David Connelly
  */
-public
-interface Checksum {
+public interface Checksum {
+
     /**
      * Updates the current checksum with the specified byte.
      *
@@ -41,6 +42,24 @@
 
     /**
      * Updates the current checksum with the specified array of bytes.
+     *
+     * @implSpec This default implementation is equal to calling
+     * {@code update(b, 0, b.length)}.
+     *
+     * @param b the array of bytes to update the checksum with
+     *
+     * @throws NullPointerException
+     *         if {@code b} is {@code null}
+     *
+     * @since 1.9
+     */
+    default public void update(byte[] b) {
+        update(b, 0, b.length);
+    }
+
+    /**
+     * Updates the current checksum with the specified array of bytes.
+     *
      * @param b the byte array to update the checksum with
      * @param off the start offset of the data
      * @param len the number of bytes to use for the update
@@ -48,7 +67,64 @@
     public void update(byte[] b, int off, int len);
 
     /**
+     * Updates the current checksum with the bytes from the specified buffer.
+     *
+     * The checksum is updated with the remaining bytes in the buffer, starting
+     * at the buffer's position. Upon return, the buffer's position will be
+     * updated to its limit; its limit will not have been changed.
+     *
+     * @apiNote For best performance with DirectByteBuffer and other ByteBuffer
+     * implementations without a backing array implementers of this interface
+     * should override this method.
+     *
+     * @implSpec The default implementation has the following behavior.<br>
+     * For ByteBuffers backed by an accessible byte array.
+     * <pre>{@code
+     * update(buffer.array(),
+     *        buffer.position() + buffer.arrayOffset(),
+     *        buffer.remaining());
+     * }</pre>
+     * For ByteBuffers not backed by an accessible byte array.
+     * <pre>{@code
+     * byte[] b = new byte[Math.min(buffer.remaining(), 4096)];
+     * while (buffer.hasRemaining()) {
+     *     int length = Math.min(buffer.remaining(), b.length);
+     *     buffer.get(b, 0, length);
+     *     update(b, 0, length);
+     * }
+     * }</pre>
+     *
+     * @param buffer the ByteBuffer to update the checksum with
+     *
+     * @throws NullPointerException
+     *         if {@code buffer} is {@code null}
+     *
+     * @since 1.9
+     */
+    default public void update(ByteBuffer buffer) {
+        int pos = buffer.position();
+        int limit = buffer.limit();
+        assert (pos <= limit);
+        int rem = limit - pos;
+        if (rem <= 0) {
+            return;
+        }
+        if (buffer.hasArray()) {
+            update(buffer.array(), pos + buffer.arrayOffset(), rem);
+        } else {
+            byte[] b = new byte[Math.min(buffer.remaining(), 4096)];
+            while (buffer.hasRemaining()) {
+                int length = Math.min(buffer.remaining(), b.length);
+                buffer.get(b, 0, length);
+                update(b, 0, length);
+            }
+        }
+        buffer.position(limit);
+    }
+
+    /**
      * Returns the current checksum value.
+     *
      * @return the current checksum value
      */
     public long getValue();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/java/util/zip/package-info.java	Fri Nov 21 09:28:53 2014 -0800
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Provides classes for reading and writing the standard ZIP and GZIP file
+ * formats. Also includes classes for compressing and decompressing data using
+ * the DEFLATE compression algorithm, which is used by the ZIP and GZIP file
+ * formats. Additionally, there are utility classes for computing the CRC-32,
+ * CRC-32C and Adler-32 checksums of arbitrary input streams.
+ *
+ * <h2>Package Specification</h2>
+ *
+ * <ul>
+ *     <li><a href="http://www.info-zip.org/doc/appnote-19970311-iz.zip">
+ *         Info-ZIP Application Note 970311</a> - a detailed description of
+ *         the Info-ZIP format upon which the {@code java.util.zip} classes
+ *         are based.
+ *     <li><a name="zip64">An implementation may optionally support the
+ *         ZIP64(tm) format extensions defined by the</a>
+ *         <a href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">
+ *         PKWARE ZIP File Format Specification</a>. The ZIP64(tm) format
+ *         extensions are used to overcome the size limitations of the
+ *         original ZIP format.
+ *     <li><a name="lang_encoding">APPENDIX D of</a>
+ *         <a href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">
+ *         PKWARE ZIP File Format Specification</a> - Language Encoding Flag
+ *         (EFS) to encode ZIP entry filename and comment fields using UTF-8.
+ *     <li><a href="http://www.ietf.org/rfc/rfc1950.txt">
+ *         ZLIB Compressed Data Format Specification version 3.3</a>
+ *         &nbsp;
+ *         <a href="http://www.ietf.org/rfc/rfc1950.txt.pdf">(pdf)</a>
+ *         (RFC 1950)
+ *     <li><a href="http://www.ietf.org/rfc/rfc1951.txt">
+ *         DEFLATE Compressed Data Format Specification version 1.3</a>
+ *         &nbsp;
+ *         <a href="http://www.ietf.org/rfc/rfc1951.txt.pdf">(pdf)</a>
+ *         (RFC 1951)
+ *     <li><a href="http://www.ietf.org/rfc/rfc1952.txt">
+ *         GZIP file format specification version 4.3</a>
+ *         &nbsp;
+ *         <a href="http://www.ietf.org/rfc/rfc1952.txt.pdf">(pdf)</a>
+ *         (RFC 1952)
+ *     <li>CRC-32 checksum is described in RFC 1952 (above)
+ *     <li>CRC-32C checksum is described in
+ *         <a href="http://www.ietf.org/rfc/rfc3720.txt">Internet Small
+ *         Computer Systems Interface (iSCSI)</a>
+ *         &nbsp;
+ *         <a href="http://www.ietf.org/rfc/rfc3720.txt.pdf">(pdf)</a>
+ *         (RFC 3720)
+ *     <li>Adler-32 checksum is described in RFC 1950 (above)
+ * </ul>
+ *
+ * @since 1.1
+ */
+package java.util.zip;
--- a/jdk/src/java.base/share/classes/java/util/zip/package.html	Fri Nov 21 16:05:11 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,88 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
-<html>
-<head>
-<!--
-Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
-DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-
-This code is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License version 2 only, as
-published by the Free Software Foundation.  Oracle designates this
-particular file as subject to the "Classpath" exception as provided
-by Oracle in the LICENSE file that accompanied this code.
-
-This code is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-version 2 for more details (a copy is included in the LICENSE file that
-accompanied this code).
-
-You should have received a copy of the GNU General Public License version
-2 along with this work; if not, write to the Free Software Foundation,
-Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-
-Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-or visit www.oracle.com if you need additional information or have any
-questions.
--->
-
-</head>
-<body bgcolor="white">
-
-Provides classes for reading and writing the standard ZIP and GZIP
-file formats.  Also includes classes for compressing and decompressing
-data using the DEFLATE compression algorithm, which is used by the
-ZIP and GZIP file formats. Additionally, there are utility classes
-for computing the CRC-32 and Adler-32 checksums of arbitrary
-input streams.
-
-
-<h2>Package Specification</h2>
-
-<ul>
-  <li><a href="http://www.info-zip.org/doc/appnote-19970311-iz.zip">
-      Info-ZIP Application Note 970311
-      </a> - a detailed description of the Info-ZIP format upon which
-      the <code>java.util.zip</code> classes are based.
-  <li><a name="zip64">An implementation may optionally support the ZIP64(tm) format extensions
-      defined by the </a>
-      <a href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">
-      PKWARE ZIP File Format Specification</a>. The ZIP64(tm) format extensions
-      are used to overcome the size limitations of the original ZIP format.
-  <li><a name="lang_encoding">APPENDIX D of </a><a href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">
-      PKWARE ZIP File Format Specification</a> - Language Encoding Flag (EFS) to
-      encode ZIP entry filename and comment fields using UTF-8.
-  <li><a href="http://www.ietf.org/rfc/rfc1950.txt">
-      ZLIB Compressed Data Format Specification version 3.3</a>
-      &nbsp;
-      <a href="http://www.ietf.org/rfc/rfc1950.txt.pdf">(pdf)</a>
-      (RFC 1950)
-  <li><a href="http://www.ietf.org/rfc/rfc1951.txt">
-      DEFLATE Compressed Data Format Specification version 1.3</a>
-      &nbsp;
-      <a href="http://www.ietf.org/rfc/rfc1951.txt.pdf">(pdf)</a>
-      (RFC 1951)
-  <li><a href="http://www.ietf.org/rfc/rfc1952.txt">
-      GZIP file format specification version 4.3</a>
-      &nbsp;
-      <a href="http://www.ietf.org/rfc/rfc1952.txt.pdf">(pdf)</a>
-      (RFC 1952)
-  <li>CRC-32 checksum is described in RFC 1952 (above)
-  <li>Adler-32 checksum is described in RFC 1950 (above)
-</ul>
-
-
-<!--
-<h2>Related Documentation</h2>
-
-For overviews, tutorials, examples, guides, and tool documentation, please see:
-<ul>
-  <li><a href="">##### REFER TO NON-SPEC DOCUMENTATION HERE #####</a>
-</ul>
--->
-
-@since 1.1
-</body>
-</html>
-
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/zip/ChecksumBase.java	Fri Nov 21 09:28:53 2014 -0800
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Base class for Checksum tests
+ */
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.charset.StandardCharsets;
+import java.util.zip.Checksum;
+
+public class ChecksumBase {
+
+    private final static byte[] BYTES_123456789 = "123456789".getBytes(StandardCharsets.US_ASCII);
+
+    public static void testAll(Checksum checksum, long expected) {
+        testBytes(checksum, expected);
+        testByteArray(checksum, expected);
+        testWrappedByteBuffer(checksum, expected);
+        testReadonlyByteBuffer(checksum, expected);
+        testDirectByteBuffer(checksum, expected);
+        testByteArrayOffset(checksum, expected);
+        testDirectByteBufferOffset(checksum, expected);
+        testLittleEndianDirectByteBufferOffset(checksum, expected);
+        testWrappedByteBufferOffset(checksum, expected);
+        testLittleEndianWrappedByteBufferOffset(checksum, expected);
+        testReadonlyByteBufferOffset(checksum, expected);
+        testLittleEndianReadonlyByteBufferOffset(checksum, expected);
+    }
+
+    private static void testBytes(Checksum checksum, long expected) {
+        checksum.reset();
+        for (byte bits : BYTES_123456789) {
+            checksum.update(bits);
+        }
+        checkChecksum(checksum, expected);
+    }
+
+    private static void testByteArray(Checksum checksum, long expected) {
+        checksum.reset();
+        checksum.update(BYTES_123456789);
+        checkChecksum(checksum, expected);
+    }
+
+    private static void testWrappedByteBuffer(Checksum checksum, long expected) {
+        checksum.reset();
+        ByteBuffer bb = ByteBuffer.wrap(BYTES_123456789);
+        checksum.update(bb);
+        checkChecksum(checksum, expected);
+    }
+
+    private static void testReadonlyByteBuffer(Checksum checksum, long expected) {
+        checksum.reset();
+        ByteBuffer bb = ByteBuffer.wrap(BYTES_123456789).asReadOnlyBuffer();
+        checksum.update(bb);
+        checkChecksum(checksum, expected);
+    }
+
+    private static void testDirectByteBuffer(Checksum checksum, long expected) {
+        checksum.reset();
+        ByteBuffer bb = ByteBuffer.allocateDirect(BYTES_123456789.length);
+        bb.put(BYTES_123456789);
+        bb.rewind();
+        checksum.update(bb);
+        checkChecksum(checksum, expected);
+    }
+
+    private static void checkChecksum(Checksum checksum, long expected) {
+        if (checksum.getValue() != expected) {
+            throw new RuntimeException("Calculated checksum result was invalid."
+                    + " Expected " + Long.toHexString(expected)
+                    + ", but got " + Long.toHexString(checksum.getValue()) + ".");
+        }
+    }
+
+    private static void testByteArrayOffset(Checksum checksum, long expected) {
+        byte[] unaligned_bytes_123456789 = new byte[BYTES_123456789.length + 64];
+        for (int i = 0; i < unaligned_bytes_123456789.length - BYTES_123456789.length; i++) {
+            checksum.reset();
+            System.arraycopy(BYTES_123456789, 0, unaligned_bytes_123456789, i, BYTES_123456789.length);
+            checksum.update(unaligned_bytes_123456789, i, BYTES_123456789.length);
+            checkChecksumOffset(checksum, expected, i);
+        }
+    }
+
+    private static void testDirectByteBufferOffset(Checksum checksum, long expected) {
+        byte[] unaligned_bytes_123456789 = new byte[BYTES_123456789.length + 64];
+        for (int i = 0; i < unaligned_bytes_123456789.length - BYTES_123456789.length; i++) {
+            checksum.reset();
+            ByteBuffer bb = ByteBuffer.allocateDirect(unaligned_bytes_123456789.length);
+            System.arraycopy(BYTES_123456789, 0, unaligned_bytes_123456789, i, BYTES_123456789.length);
+            bb.put(unaligned_bytes_123456789);
+            bb.position(i);
+            bb.limit(i + BYTES_123456789.length);
+            checksum.update(bb);
+            checkChecksumOffset(checksum, expected, i);
+        }
+    }
+
+    private static void testLittleEndianDirectByteBufferOffset(Checksum checksum, long expected) {
+        byte[] unaligned_bytes_123456789 = new byte[BYTES_123456789.length + 64];
+        for (int i = 0; i < unaligned_bytes_123456789.length - BYTES_123456789.length; i++) {
+            checksum.reset();
+            ByteBuffer bb = ByteBuffer.allocateDirect(unaligned_bytes_123456789.length);
+            bb.order(ByteOrder.LITTLE_ENDIAN);
+            System.arraycopy(BYTES_123456789, 0, unaligned_bytes_123456789, i, BYTES_123456789.length);
+            bb.put(unaligned_bytes_123456789);
+            bb.position(i);
+            bb.limit(i + BYTES_123456789.length);
+            checksum.update(bb);
+            checkChecksumOffset(checksum, expected, i);
+        }
+    }
+
+    private static void testWrappedByteBufferOffset(Checksum checksum, long expected) {
+        byte[] unaligned_bytes_123456789 = new byte[BYTES_123456789.length + 64];
+        for (int i = 0; i < unaligned_bytes_123456789.length - BYTES_123456789.length; i++) {
+            checksum.reset();
+            System.arraycopy(BYTES_123456789, 0, unaligned_bytes_123456789, i, BYTES_123456789.length);
+            ByteBuffer bb = ByteBuffer.wrap(unaligned_bytes_123456789);
+            bb.position(i);
+            bb.limit(i + BYTES_123456789.length);
+            checksum.update(bb);
+            checkChecksumOffset(checksum, expected, i);
+        }
+    }
+
+    private static void testLittleEndianWrappedByteBufferOffset(Checksum checksum, long expected) {
+        byte[] unaligned_bytes_123456789 = new byte[BYTES_123456789.length + 64];
+        for (int i = 0; i < unaligned_bytes_123456789.length - BYTES_123456789.length; i++) {
+            checksum.reset();
+            System.arraycopy(BYTES_123456789, 0, unaligned_bytes_123456789, i, BYTES_123456789.length);
+            ByteBuffer bb = ByteBuffer.wrap(unaligned_bytes_123456789);
+            bb.order(ByteOrder.LITTLE_ENDIAN);
+            bb.position(i);
+            bb.limit(i + BYTES_123456789.length);
+            checksum.update(bb);
+            checkChecksumOffset(checksum, expected, i);
+        }
+    }
+
+    private static void testReadonlyByteBufferOffset(Checksum checksum, long expected) {
+        byte[] unaligned_bytes_123456789 = new byte[BYTES_123456789.length + 64];
+        for (int i = 0; i < unaligned_bytes_123456789.length - BYTES_123456789.length; i++) {
+            checksum.reset();
+            System.arraycopy(BYTES_123456789, 0, unaligned_bytes_123456789, i, BYTES_123456789.length);
+            ByteBuffer bb = ByteBuffer.wrap(unaligned_bytes_123456789).asReadOnlyBuffer();
+            bb.position(i);
+            bb.limit(i + BYTES_123456789.length);
+            checksum.update(bb);
+            checkChecksumOffset(checksum, expected, i);
+        }
+    }
+
+    private static void testLittleEndianReadonlyByteBufferOffset(Checksum checksum, long expected) {
+        byte[] unaligned_bytes_123456789 = new byte[BYTES_123456789.length + 64];
+        for (int i = 0; i < unaligned_bytes_123456789.length - BYTES_123456789.length; i++) {
+            checksum.reset();
+            System.arraycopy(BYTES_123456789, 0, unaligned_bytes_123456789, i, BYTES_123456789.length);
+            ByteBuffer bb = ByteBuffer.wrap(unaligned_bytes_123456789).asReadOnlyBuffer();
+            bb.order(ByteOrder.LITTLE_ENDIAN);
+            bb.position(i);
+            bb.limit(i + BYTES_123456789.length);
+            checksum.update(bb);
+            checkChecksumOffset(checksum, expected, i);
+        }
+    }
+
+    private static void checkChecksumOffset(Checksum checksum, long expected, int offset) {
+        if (checksum.getValue() != expected) {
+            throw new RuntimeException("Calculated CRC32C result was invalid. Array offset "
+                    + offset + ". Expected: " + Long.toHexString(expected) + ", Got: "
+                    + Long.toHexString(checksum.getValue()));
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/zip/TestCRC32.java	Fri Nov 21 09:28:53 2014 -0800
@@ -0,0 +1,40 @@
+
+import java.util.zip.CRC32;
+
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test @summary Check that CRC-32 returns the expected CRC value for the
+ * string 123456789
+ * http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat.crc-32
+ * @build ChecksumBase
+ * @run main TestCRC32
+ */
+
+public class TestCRC32 {
+
+    public static void main(String[] args) {
+        ChecksumBase.testAll(new CRC32(), 0xCBF43926L);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/zip/TestCRC32C.java	Fri Nov 21 09:28:53 2014 -0800
@@ -0,0 +1,40 @@
+
+import java.util.zip.CRC32C;
+
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test @summary Check that CRC-32C returns the expected CRC value for the
+ * string 123456789
+ * http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat.crc-32c
+ * @build ChecksumBase
+ * @run main TestCRC32C
+ */
+
+public class TestCRC32C {
+
+    public static void main(String[] args) {
+        ChecksumBase.testAll(new CRC32C(), 0xE3069283L);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/zip/TestChecksum.java	Fri Nov 21 09:28:53 2014 -0800
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test @summary Test that default methods in Checksum works as expected
+ * @build ChecksumBase
+ * @run main TestChecksum
+ */
+import java.util.zip.CRC32C;
+import java.util.zip.Checksum;
+
+public class TestChecksum {
+
+    public static void main(String[] args) {
+        ChecksumBase.testAll(new MyCRC32C(), 0xE3069283L);
+    }
+
+    /**
+     * Only implementing required methods
+     */
+    private static class MyCRC32C implements Checksum {
+
+        private final CRC32C crc32c = new CRC32C();
+
+        @Override
+        public void update(int b) {
+            crc32c.update(b);
+        }
+
+        @Override
+        public void update(byte[] b, int off, int len) {
+            crc32c.update(b, off, len);
+        }
+
+        @Override
+        public long getValue() {
+            return crc32c.getValue();
+        }
+
+        @Override
+        public void reset() {
+            crc32c.reset();
+        }
+
+    }
+}