Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-6512111

final long stack variable gets corrupted when FileChannel read is interrupted

XMLWordPrintable

    • 6
    • b07
    • x86
    • windows_xp

        FULL PRODUCT VERSION :
        1.6.0-b105

        ADDITIONAL OS VERSION INFORMATION :
        Microsoft Windows XP [Version 5.1.2600]

        A DESCRIPTION OF THE PROBLEM :
        final long stack variable gets corrupted when FileChannel read is interrupted

        STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
        run the main method in provided source code

        EXPECTED VERSUS ACTUAL BEHAVIOR :
        EXPECTED -
        final long variable value remains constant
        ACTUAL -
        final long variable value gets corrupted during program execution

        REPRODUCIBILITY :
        This bug can be reproduced always.

        ---------- BEGIN SOURCE ----------
        import java.io.BufferedOutputStream;
        import java.io.File;
        import java.io.FileInputStream;
        import java.io.FileOutputStream;
        import java.io.IOException;
        import java.io.OutputStream;
        import java.nio.ByteBuffer;
        import java.nio.channels.ByteChannel;
        import java.security.MessageDigest;
        import java.util.Date;
        import java.util.Random;

        public class CorruptFinalLong {

        private static final Random random = new Random();

        private static void createFileIfNeeded(File file) throws IOException {
        if (!file.exists()) {
        int bufSize = 1000000;
        int rounds = 50;
        System.out.println("writing random file " + file + " of size " + (bufSize * rounds)
        + " bytes");
        byte[] buf = new byte[bufSize];
        OutputStream out = new BufferedOutputStream(new FileOutputStream(file), 65536);
        for (int i = 0; i < rounds; i++) {
        random.nextBytes(buf);
        out.write(buf);
        }
        out.close();
        }
        }

        public static void main(String[] args) throws Exception {

        System.setErr(System.out);

        String[] props = new String[] { "java.vm.version", "java.vm.name", "sun.os.patch.level",
        "java.runtime.version", "java.vm.version", "os.arch", "os.name",
        "java.specification.version", "java.vm.specification.version",
        "java.specification.vendor", "java.version" };

        for (String p : props) {
        System.out.printf("%30s: %s", p, System.getProperty(p));
        System.out.println();
        }
        System.out.println();

        final File file = new File("random.dat");

        createFileIfNeeded(file);

        final Thread t = Thread.currentThread();

        new Thread(new Runnable() {
        public void run() {
        try {
        Thread.sleep(1000);
        System.out.println("\tabout to interrupt thread '" + t + "' from thread '"
        + Thread.currentThread() + "'");
        t.interrupt();
        } catch (InterruptedException e) {
        System.out.println("\tinterrupted in thread");
        e.printStackTrace();
        }

        }
        }).start();

        final long start = System.currentTimeMillis();
        System.out.println("started at " + new Date(start) + " (" + start + " ms)");
        System.out.println();

        MessageDigest md = MessageDigest.getInstance("MD5");

        ByteChannel channel = new FileInputStream(file).getChannel();
        try {
        int cap = 10;
        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(cap);
        byte[] local = new byte[cap];
        long lastRead = 0;
        boolean eof = false;
        while (!eof) {
        byteBuffer.rewind();
        int bytesReadThisTime = channel.read(byteBuffer);
        if (bytesReadThisTime == -1) {
        eof = true;
        } else {
        // totalRead += bytesReadThisTime;
        byteBuffer.rewind();
        byteBuffer.get(local, 0, bytesReadThisTime);
        md.update(local, 0, bytesReadThisTime);
        if (System.currentTimeMillis() - lastRead > 1000) {
        lastRead = System.currentTimeMillis();
        }
        }
        }
        } catch (Exception e) {
        if (Thread.interrupted()) {
        System.out.println("\t********* IO was interrupted in thread '"
        + Thread.currentThread() + "': " + e);
        } else {
        System.out.println("\texception: " + e);
        }
        } finally {
        channel.close();
        }

        System.out.println();
        System.out
        .println("the following line should be identical to the similar one above, since variable 'start' is final:");
        System.out.println("started at " + new Date(start) + " (" + start + " ms)");

        }

        }

        ---------- END SOURCE ----------

        CUSTOMER SUBMITTED WORKAROUND :
        none --- aside from reverting to java 5.0

              never Tom Rodriguez
              ndcosta Nelson Dcosta (Inactive)
              Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

                Created:
                Updated:
                Resolved:
                Imported:
                Indexed: