changeset 6262:bcba89ce0a8c

8003322: Add instrumentation points for tracing of I/O calls Reviewed-by: alanb, mchung
author sla
date Tue, 27 Nov 2012 09:23:54 +0100
parents a9fb42752972
children 580e399d49a5
files make/java/java/mapfile-vers src/share/classes/java/io/FileInputStream.java src/share/classes/java/io/FileOutputStream.java src/share/classes/java/io/RandomAccessFile.java src/share/classes/java/net/SocketInputStream.java src/share/classes/java/net/SocketOutputStream.java src/share/classes/sun/misc/IoTrace.java src/share/classes/sun/nio/ch/FileChannelImpl.java src/share/classes/sun/nio/ch/SocketAdaptor.java src/share/classes/sun/nio/ch/SocketChannelImpl.java src/share/native/java/io/FileInputStream.c src/share/native/java/io/RandomAccessFile.c src/solaris/classes/sun/nio/fs/SolarisUserDefinedFileAttributeView.java src/solaris/classes/sun/nio/fs/UnixChannelFactory.java src/windows/classes/sun/nio/fs/WindowsChannelFactory.java test/sun/misc/IoTrace/IoTraceAgent.java test/sun/misc/IoTrace/IoTraceBase.java test/sun/misc/IoTrace/IoTraceFileChannelReadWrite.java test/sun/misc/IoTrace/IoTraceFileReadWrite.java test/sun/misc/IoTrace/IoTraceListener.java test/sun/misc/IoTrace/IoTraceSocketReadWrite.java test/sun/misc/IoTrace/ioTraceTest.sh test/sun/misc/IoTrace/iotraceagent.mf
diffstat 23 files changed, 1128 insertions(+), 41 deletions(-) [+]
line wrap: on
line diff
--- a/make/java/java/mapfile-vers	Fri Jun 24 19:30:39 2011 +0100
+++ b/make/java/java/mapfile-vers	Tue Nov 27 09:23:54 2012 +0100
@@ -79,7 +79,7 @@
 		Java_java_io_FileInputStream_close0;
 		Java_java_io_FileInputStream_initIDs;
 		Java_java_io_FileInputStream_open;
-		Java_java_io_FileInputStream_read;
+		Java_java_io_FileInputStream_read0;
 		Java_java_io_FileInputStream_readBytes;
 		Java_java_io_FileInputStream_skip;
 		Java_java_io_FileOutputStream_close0;
@@ -100,12 +100,12 @@
 		Java_java_io_RandomAccessFile_initIDs;
 		Java_java_io_RandomAccessFile_length;
 		Java_java_io_RandomAccessFile_open;
-		Java_java_io_RandomAccessFile_read;
-		Java_java_io_RandomAccessFile_readBytes;
+		Java_java_io_RandomAccessFile_read0;
+		Java_java_io_RandomAccessFile_readBytes0;
 		Java_java_io_RandomAccessFile_seek;
 		Java_java_io_RandomAccessFile_setLength;
-		Java_java_io_RandomAccessFile_write;
-		Java_java_io_RandomAccessFile_writeBytes;
+		Java_java_io_RandomAccessFile_write0;
+		Java_java_io_RandomAccessFile_writeBytes0;
 		Java_java_io_UnixFileSystem_canonicalize0;
 		Java_java_io_UnixFileSystem_checkAccess;
 		Java_java_io_UnixFileSystem_createDirectory;
--- a/src/share/classes/java/io/FileInputStream.java	Fri Jun 24 19:30:39 2011 +0100
+++ b/src/share/classes/java/io/FileInputStream.java	Tue Nov 27 09:23:54 2012 +0100
@@ -27,6 +27,7 @@
 
 import java.nio.channels.FileChannel;
 import sun.nio.ch.FileChannelImpl;
+import sun.misc.IoTrace;
 
 
 /**
@@ -51,6 +52,9 @@
     /* File Descriptor - handle to the open file */
     private final FileDescriptor fd;
 
+    /* The path of the referenced file (null if the stream is created with a file descriptor) */
+    private final String path;
+
     private FileChannel channel = null;
 
     private final Object closeLock = new Object();
@@ -135,6 +139,7 @@
         }
         fd = new FileDescriptor();
         fd.incrementAndGetUseCount();
+        this.path = name;
         open(name);
     }
 
@@ -171,6 +176,7 @@
             security.checkRead(fdObj);
         }
         fd = fdObj;
+        path = null;
 
         /*
          * FileDescriptor is being shared by streams.
@@ -194,7 +200,18 @@
      *             file is reached.
      * @exception  IOException  if an I/O error occurs.
      */
-    public native int read() throws IOException;
+    public int read() throws IOException {
+        Object traceContext = IoTrace.fileReadBegin(path);
+        int b = 0;
+        try {
+            b = read0();
+        } finally {
+            IoTrace.fileReadEnd(traceContext, b == -1 ? 0 : 1);
+        }
+        return b;
+    }
+
+    private native int read0() throws IOException;
 
     /**
      * Reads a subarray as a sequence of bytes.
@@ -217,7 +234,14 @@
      * @exception  IOException  if an I/O error occurs.
      */
     public int read(byte b[]) throws IOException {
-        return readBytes(b, 0, b.length);
+        Object traceContext = IoTrace.fileReadBegin(path);
+        int bytesRead = 0;
+        try {
+            bytesRead = readBytes(b, 0, b.length);
+        } finally {
+            IoTrace.fileReadEnd(traceContext, bytesRead == -1 ? 0 : bytesRead);
+        }
+        return bytesRead;
     }
 
     /**
@@ -239,7 +263,14 @@
      * @exception  IOException  if an I/O error occurs.
      */
     public int read(byte b[], int off, int len) throws IOException {
-        return readBytes(b, off, len);
+        Object traceContext = IoTrace.fileReadBegin(path);
+        int bytesRead = 0;
+        try {
+            bytesRead = readBytes(b, off, len);
+        } finally {
+            IoTrace.fileReadEnd(traceContext, bytesRead == -1 ? 0 : bytesRead);
+        }
+        return bytesRead;
     }
 
     /**
@@ -361,7 +392,7 @@
     public FileChannel getChannel() {
         synchronized (this) {
             if (channel == null) {
-                channel = FileChannelImpl.open(fd, true, false, this);
+                channel = FileChannelImpl.open(fd, path, true, false, this);
 
                 /*
                  * Increment fd's use count. Invoking the channel's close()
--- a/src/share/classes/java/io/FileOutputStream.java	Fri Jun 24 19:30:39 2011 +0100
+++ b/src/share/classes/java/io/FileOutputStream.java	Tue Nov 27 09:23:54 2012 +0100
@@ -27,6 +27,7 @@
 
 import java.nio.channels.FileChannel;
 import sun.nio.ch.FileChannelImpl;
+import sun.misc.IoTrace;
 
 
 /**
@@ -58,6 +59,11 @@
     private final FileDescriptor fd;
 
     /**
+     * The path of the referenced file (null if the stream is created with a file descriptor)
+     */
+    private final String path;
+
+    /**
      * True if the file is opened for append.
      */
     private final boolean append;
@@ -207,7 +213,7 @@
         }
         this.fd = new FileDescriptor();
         this.append = append;
-
+        this.path = name;
         fd.incrementAndGetUseCount();
         open(name, append);
     }
@@ -244,6 +250,7 @@
             security.checkWrite(fdObj);
         }
         this.fd = fdObj;
+        this.path = null;
         this.append = false;
 
         /*
@@ -279,7 +286,14 @@
      * @exception  IOException  if an I/O error occurs.
      */
     public void write(int b) throws IOException {
-        write(b, append);
+        Object traceContext = IoTrace.fileWriteBegin(path);
+        int bytesWritten = 0;
+        try {
+            write(b, append);
+            bytesWritten = 1;
+        } finally {
+            IoTrace.fileWriteEnd(traceContext, bytesWritten);
+        }
     }
 
     /**
@@ -302,7 +316,14 @@
      * @exception  IOException  if an I/O error occurs.
      */
     public void write(byte b[]) throws IOException {
-        writeBytes(b, 0, b.length, append);
+        Object traceContext = IoTrace.fileWriteBegin(path);
+        int bytesWritten = 0;
+        try {
+            writeBytes(b, 0, b.length, append);
+            bytesWritten = b.length;
+        } finally {
+            IoTrace.fileWriteEnd(traceContext, bytesWritten);
+        }
     }
 
     /**
@@ -315,7 +336,14 @@
      * @exception  IOException  if an I/O error occurs.
      */
     public void write(byte b[], int off, int len) throws IOException {
-        writeBytes(b, off, len, append);
+        Object traceContext = IoTrace.fileWriteBegin(path);
+        int bytesWritten = 0;
+        try {
+            writeBytes(b, off, len, append);
+            bytesWritten = len;
+        } finally {
+            IoTrace.fileWriteEnd(traceContext, bytesWritten);
+        }
     }
 
     /**
@@ -398,7 +426,7 @@
     public FileChannel getChannel() {
         synchronized (this) {
             if (channel == null) {
-                channel = FileChannelImpl.open(fd, false, true, append, this);
+                channel = FileChannelImpl.open(fd, path, false, true, append, this);
 
                 /*
                  * Increment fd's use count. Invoking the channel's close()
--- a/src/share/classes/java/io/RandomAccessFile.java	Fri Jun 24 19:30:39 2011 +0100
+++ b/src/share/classes/java/io/RandomAccessFile.java	Tue Nov 27 09:23:54 2012 +0100
@@ -27,6 +27,7 @@
 
 import java.nio.channels.FileChannel;
 import sun.nio.ch.FileChannelImpl;
+import sun.misc.IoTrace;
 
 
 /**
@@ -62,6 +63,9 @@
     private FileChannel channel = null;
     private boolean rw;
 
+    /* The path of the referenced file */
+    private final String path;
+
     private Object closeLock = new Object();
     private volatile boolean closed = false;
 
@@ -230,6 +234,7 @@
         }
         fd = new FileDescriptor();
         fd.incrementAndGetUseCount();
+        this.path = name;
         open(name, imode);
     }
 
@@ -267,7 +272,7 @@
     public final FileChannel getChannel() {
         synchronized (this) {
             if (channel == null) {
-                channel = FileChannelImpl.open(fd, true, rw, this);
+                channel = FileChannelImpl.open(fd, path, true, rw, this);
 
                 /*
                  * FileDescriptor could be shared by FileInputStream or
@@ -315,7 +320,18 @@
      * @exception  IOException  if an I/O error occurs. Not thrown if
      *                          end-of-file has been reached.
      */
-    public native int read() throws IOException;
+    public int read() throws IOException {
+        Object traceContext = IoTrace.fileReadBegin(path);
+        int b = 0;
+        try {
+            b = read0();
+        } finally {
+            IoTrace.fileReadEnd(traceContext, b == -1 ? 0 : 1);
+        }
+        return b;
+    }
+
+    private native int read0() throws IOException;
 
     /**
      * Reads a sub array as a sequence of bytes.
@@ -324,7 +340,18 @@
      * @param len the number of bytes to read.
      * @exception IOException If an I/O error has occurred.
      */
-    private native int readBytes(byte b[], int off, int len) throws IOException;
+    private int readBytes(byte b[], int off, int len) throws IOException {
+        Object traceContext = IoTrace.fileReadBegin(path);
+        int bytesRead = 0;
+        try {
+            bytesRead = readBytes0(b, off, len);
+        } finally {
+            IoTrace.fileReadEnd(traceContext, bytesRead == -1 ? 0 : bytesRead);
+        }
+        return bytesRead;
+    }
+
+    private native int readBytes0(byte b[], int off, int len) throws IOException;
 
     /**
      * Reads up to <code>len</code> bytes of data from this file into an
@@ -463,17 +490,38 @@
      * @param      b   the <code>byte</code> to be written.
      * @exception  IOException  if an I/O error occurs.
      */
-    public native void write(int b) throws IOException;
+    public void write(int b) throws IOException {
+        Object traceContext = IoTrace.fileWriteBegin(path);
+        int bytesWritten = 0;
+        try {
+            write0(b);
+            bytesWritten = 1;
+        } finally {
+            IoTrace.fileWriteEnd(traceContext, bytesWritten);
+        }
+    }
+
+    private native void write0(int b) throws IOException;
 
     /**
      * Writes a sub array as a sequence of bytes.
      * @param b the data to be written
-
      * @param off the start offset in the data
      * @param len the number of bytes that are written
      * @exception IOException If an I/O error has occurred.
      */
-    private native void writeBytes(byte b[], int off, int len) throws IOException;
+    private void writeBytes(byte b[], int off, int len) throws IOException {
+        Object traceContext = IoTrace.fileWriteBegin(path);
+        int bytesWritten = 0;
+        try {
+            writeBytes0(b, off, len);
+            bytesWritten = len;
+        } finally {
+            IoTrace.fileWriteEnd(traceContext, bytesWritten);
+        }
+    }
+
+    private native void writeBytes0(byte b[], int off, int len) throws IOException;
 
     /**
      * Writes <code>b.length</code> bytes from the specified byte array
--- a/src/share/classes/java/net/SocketInputStream.java	Fri Jun 24 19:30:39 2011 +0100
+++ b/src/share/classes/java/net/SocketInputStream.java	Tue Nov 27 09:23:54 2012 +0100
@@ -30,6 +30,7 @@
 import java.io.IOException;
 import java.nio.channels.FileChannel;
 
+import sun.misc.IoTrace;
 import sun.net.ConnectionResetException;
 
 /**
@@ -122,7 +123,7 @@
     }
 
     int read(byte b[], int off, int length, int timeout) throws IOException {
-        int n;
+        int n = 0;
 
         // EOF already encountered
         if (eof) {
@@ -144,6 +145,7 @@
 
         boolean gotReset = false;
 
+        Object traceContext = IoTrace.socketReadBegin(impl.address, impl.port, timeout);
         // acquire file descriptor and do the read
         FileDescriptor fd = impl.acquireFD();
         try {
@@ -155,6 +157,7 @@
             gotReset = true;
         } finally {
             impl.releaseFD();
+            IoTrace.socketReadEnd(traceContext, n > 0 ? n : 0);
         }
 
         /*
@@ -162,6 +165,7 @@
          * buffered on the socket
          */
         if (gotReset) {
+            traceContext = IoTrace.socketReadBegin(impl.address, impl.port, timeout);
             impl.setConnectionResetPending();
             impl.acquireFD();
             try {
@@ -172,6 +176,7 @@
             } catch (ConnectionResetException rstExc) {
             } finally {
                 impl.releaseFD();
+                IoTrace.socketReadEnd(traceContext, n > 0 ? n : 0);
             }
         }
 
--- a/src/share/classes/java/net/SocketOutputStream.java	Fri Jun 24 19:30:39 2011 +0100
+++ b/src/share/classes/java/net/SocketOutputStream.java	Tue Nov 27 09:23:54 2012 +0100
@@ -30,6 +30,8 @@
 import java.io.IOException;
 import java.nio.channels.FileChannel;
 
+import sun.misc.IoTrace;
+
 /**
  * This stream extends FileOutputStream to implement a
  * SocketOutputStream. Note that this class should <b>NOT</b> be
@@ -104,9 +106,12 @@
             throw new ArrayIndexOutOfBoundsException();
         }
 
+        Object traceContext = IoTrace.socketWriteBegin(impl.address, impl.port);
+        int bytesWritten = 0;
         FileDescriptor fd = impl.acquireFD();
         try {
             socketWrite0(fd, b, off, len);
+            bytesWritten = len;
         } catch (SocketException se) {
             if (se instanceof sun.net.ConnectionResetException) {
                 impl.setConnectionResetPending();
@@ -119,6 +124,7 @@
             }
         } finally {
             impl.releaseFD();
+            IoTrace.socketWriteEnd(traceContext, bytesWritten);
         }
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/sun/misc/IoTrace.java	Tue Nov 27 09:23:54 2012 +0100
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 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.
+ */
+
+package sun.misc;
+
+import java.net.InetAddress;
+
+/**
+ * Utility class used to identify trace points for I/O calls.
+ * <p>
+ * To use this class, a diagnostic tool must redefine this class with a version
+ * that contains calls to the the diagnostic tool. This implementation will then
+ * receive callbacks when file and socket operations are performed. The reason
+ * for requiring a redefine of the class is to avoid any overhead caused by the
+ * instrumentation.
+ * <p>
+ * The xxBegin() methods return a "context". This can be any Object. This
+ * context will be passed to the corresponding xxEnd() method. This way, an
+ * implementation can correlate the beginning of an operation with the end.
+ * <p>
+ * It is possible for a xxEnd() method to be called with a null handle. This
+ * happens if tracing was started between the call to xxBegin() and xxEnd(), in
+ * which case xxBegin() would not have been called. It is the implementation's
+ * responsibility to not throw an exception in this case.
+ * <p>
+ * Only blocking I/O operations are identified with this facility.
+ * <p>
+ * <b>Warning</b>
+ * <p>
+ * These methods are called from sensitive points in the I/O subsystem. Great
+ * care must be taken to not interfere with ongoing operations or cause
+ * deadlocks. In particular:
+ * <ul>
+ * <li>Implementations must not throw exceptions since this will cause
+ * disruptions to the I/O operations.
+ * <li>Implementations must not do I/O operations since this will lead to an
+ * endless loop.
+ * <li>Since the hooks may be called while holding low-level locks in the I/O
+ * subsystem, implementations must be careful with synchronization or
+ * interaction with other threads to avoid deadlocks in the VM.
+ * </ul>
+ */
+public final class IoTrace {
+    private IoTrace() {
+    }
+
+    /**
+     * Called before data is read from a socket.
+     *
+     * @param address
+     *            the remote address the socket is bound to
+     * @param port
+     *            the remote port the socket is bound to
+     * @param timeout
+     *            the SO_TIMEOUT value of the socket (in milliseconds) or 0 if
+     *            there is no timeout set
+     * @return a context object
+     */
+    public static Object socketReadBegin(InetAddress address, int port,
+            int timeout) {
+        return null;
+    }
+
+    /**
+     * Called after data is read from the socket.
+     *
+     * @param context
+     *            the context returned by the previous call to socketReadBegin()
+     * @param bytesRead
+     *            the number of bytes read from the socket, 0 if there was an
+     *            error reading from the socket
+     */
+    public static void socketReadEnd(Object context, long bytesRead) {
+    }
+
+    /**
+     * Called before data is written to a socket.
+     *
+     * @param address
+     *            the remote address the socket is bound to
+     * @param port
+     *            the remote port the socket is bound to
+     * @return a context object
+     */
+    public static Object socketWriteBegin(InetAddress address, int port) {
+        return null;
+    }
+
+    /**
+     * Called after data is written to a socket.
+     *
+     * @param context
+     *            the context returned by the previous call to
+     *            socketWriteBegin()
+     * @param bytesWritten
+     *            the number of bytes written to the socket, 0 if there was an
+     *            error writing to the socket
+     */
+    public static void socketWriteEnd(Object context, long bytesWritten) {
+    }
+
+    /**
+     * Called before data is read from a file.
+     *
+     * @param path
+     *            the path of the file
+     * @return a context object
+     */
+    public static Object fileReadBegin(String path) {
+        return null;
+    }
+
+    /**
+     * Called after data is read from a file.
+     *
+     * @param context
+     *            the context returned by the previous call to fileReadBegin()
+     * @param bytesRead
+     *            the number of bytes written to the file, 0 if there was an
+     *            error writing to the file
+     */
+    public static void fileReadEnd(Object context, long bytesRead) {
+    }
+
+    /**
+     * Called before data is written to a file.
+     *
+     * @param path
+     *            the path of the file
+     * @return a context object
+     */
+    public static Object fileWriteBegin(String path) {
+        return null;
+    }
+
+    /**
+     * Called after data is written to a file.
+     *
+     * @param context
+     *            the context returned by the previous call to fileReadBegin()
+     * @param bytesWritten
+     *            the number of bytes written to the file, 0 if there was an
+     *            error writing to the file
+     */
+    public static void fileWriteEnd(Object context, long bytesWritten) {
+    }
+}
--- a/src/share/classes/sun/nio/ch/FileChannelImpl.java	Fri Jun 24 19:30:39 2011 +0100
+++ b/src/share/classes/sun/nio/ch/FileChannelImpl.java	Tue Nov 27 09:23:54 2012 +0100
@@ -34,6 +34,7 @@
 import java.util.List;
 import java.security.AccessController;
 import sun.misc.Cleaner;
+import sun.misc.IoTrace;
 import sun.security.action.GetPropertyAction;
 
 public class FileChannelImpl
@@ -56,13 +57,16 @@
     // Required to prevent finalization of creating stream (immutable)
     private final Object parent;
 
+    // The path of the referenced file (null if the parent stream is created with a file descriptor)
+    private final String path;
+
     // Thread-safe set of IDs of native threads, for signalling
     private final NativeThreadSet threads = new NativeThreadSet(2);
 
     // Lock for operations involving position and size
     private final Object positionLock = new Object();
 
-    private FileChannelImpl(FileDescriptor fd, boolean readable,
+    private FileChannelImpl(FileDescriptor fd, String path, boolean readable,
                             boolean writable, boolean append, Object parent)
     {
         this.fd = fd;
@@ -70,23 +74,24 @@
         this.writable = writable;
         this.append = append;
         this.parent = parent;
+        this.path = path;
         this.nd = new FileDispatcherImpl(append);
     }
 
     // Used by FileInputStream.getChannel() and RandomAccessFile.getChannel()
-    public static FileChannel open(FileDescriptor fd,
+    public static FileChannel open(FileDescriptor fd, String path,
                                    boolean readable, boolean writable,
                                    Object parent)
     {
-        return new FileChannelImpl(fd, readable, writable, false, parent);
+        return new FileChannelImpl(fd, path, readable, writable, false, parent);
     }
 
     // Used by FileOutputStream.getChannel
-    public static FileChannel open(FileDescriptor fd,
+    public static FileChannel open(FileDescriptor fd, String path,
                                    boolean readable, boolean writable,
                                    boolean append, Object parent)
     {
-        return new FileChannelImpl(fd, readable, writable, append, parent);
+        return new FileChannelImpl(fd, path, readable, writable, append, parent);
     }
 
     private void ensureOpen() throws IOException {
@@ -134,6 +139,7 @@
         synchronized (positionLock) {
             int n = 0;
             int ti = -1;
+            Object traceContext = IoTrace.fileReadBegin(path);
             try {
                 begin();
                 ti = threads.add();
@@ -145,6 +151,7 @@
                 return IOStatus.normalize(n);
             } finally {
                 threads.remove(ti);
+                IoTrace.fileReadEnd(traceContext, n > 0 ? n : 0);
                 end(n > 0);
                 assert IOStatus.check(n);
             }
@@ -162,6 +169,7 @@
         synchronized (positionLock) {
             long n = 0;
             int ti = -1;
+            Object traceContext = IoTrace.fileReadBegin(path);
             try {
                 begin();
                 ti = threads.add();
@@ -173,6 +181,7 @@
                 return IOStatus.normalize(n);
             } finally {
                 threads.remove(ti);
+                IoTrace.fileReadEnd(traceContext, n > 0 ? n : 0);
                 end(n > 0);
                 assert IOStatus.check(n);
             }
@@ -186,6 +195,7 @@
         synchronized (positionLock) {
             int n = 0;
             int ti = -1;
+            Object traceContext = IoTrace.fileWriteBegin(path);
             try {
                 begin();
                 ti = threads.add();
@@ -198,6 +208,7 @@
             } finally {
                 threads.remove(ti);
                 end(n > 0);
+                IoTrace.fileWriteEnd(traceContext, n > 0 ? n : 0);
                 assert IOStatus.check(n);
             }
         }
@@ -214,6 +225,7 @@
         synchronized (positionLock) {
             long n = 0;
             int ti = -1;
+            Object traceContext = IoTrace.fileWriteBegin(path);
             try {
                 begin();
                 ti = threads.add();
@@ -225,6 +237,7 @@
                 return IOStatus.normalize(n);
             } finally {
                 threads.remove(ti);
+                IoTrace.fileWriteEnd(traceContext, n > 0 ? n : 0);
                 end(n > 0);
                 assert IOStatus.check(n);
             }
@@ -665,6 +678,7 @@
         ensureOpen();
         int n = 0;
         int ti = -1;
+        Object traceContext = IoTrace.fileReadBegin(path);
         try {
             begin();
             ti = threads.add();
@@ -676,6 +690,7 @@
             return IOStatus.normalize(n);
         } finally {
             threads.remove(ti);
+            IoTrace.fileReadEnd(traceContext, n > 0 ? n : 0);
             end(n > 0);
             assert IOStatus.check(n);
         }
@@ -691,6 +706,7 @@
         ensureOpen();
         int n = 0;
         int ti = -1;
+        Object traceContext = IoTrace.fileWriteBegin(path);
         try {
             begin();
             ti = threads.add();
@@ -703,6 +719,7 @@
         } finally {
             threads.remove(ti);
             end(n > 0);
+            IoTrace.fileWriteEnd(traceContext, n > 0 ? n : 0);
             assert IOStatus.check(n);
         }
     }
--- a/src/share/classes/sun/nio/ch/SocketAdaptor.java	Fri Jun 24 19:30:39 2011 +0100
+++ b/src/share/classes/sun/nio/ch/SocketAdaptor.java	Tue Nov 27 09:23:54 2012 +0100
@@ -34,6 +34,8 @@
 import java.security.PrivilegedExceptionAction;
 import java.util.*;
 
+import sun.misc.IoTrace;
+
 
 // Make a socket channel look like a socket.
 //
@@ -204,8 +206,9 @@
                 SelectionKey sk = null;
                 Selector sel = null;
                 sc.configureBlocking(false);
+                int n = 0;
+                Object traceContext = IoTrace.socketReadBegin(getInetAddress(), getPort(), timeout);
                 try {
-                    int n;
                     if ((n = sc.read(bb)) != 0)
                         return n;
                     sel = Util.getTemporarySelector(sc);
@@ -226,6 +229,7 @@
                             throw new SocketTimeoutException();
                     }
                 } finally {
+                    IoTrace.socketReadEnd(traceContext, n > 0 ? n : 0);
                     if (sk != null)
                         sk.cancel();
                     if (sc.isOpen())
--- a/src/share/classes/sun/nio/ch/SocketChannelImpl.java	Fri Jun 24 19:30:39 2011 +0100
+++ b/src/share/classes/sun/nio/ch/SocketChannelImpl.java	Tue Nov 27 09:23:54 2012 +0100
@@ -33,7 +33,7 @@
 import java.nio.channels.spi.*;
 import java.util.*;
 import sun.net.NetHooks;
-
+import sun.misc.IoTrace;
 
 /**
  * An implementation of SocketChannels
@@ -80,8 +80,8 @@
     private int state = ST_UNINITIALIZED;
 
     // Binding
-    private SocketAddress localAddress;
-    private SocketAddress remoteAddress;
+    private InetSocketAddress localAddress;
+    private InetSocketAddress remoteAddress;
 
     // Input/Output open
     private boolean isInputOpen = true;
@@ -278,6 +278,11 @@
         synchronized (readLock) {
             if (!ensureReadOpen())
                 return -1;
+            Object traceContext = null;
+            if (isBlocking()) {
+                traceContext = IoTrace.socketReadBegin(remoteAddress.getAddress(),
+                                                      remoteAddress.getPort(), 0);
+            }
             int n = 0;
             try {
 
@@ -367,6 +372,11 @@
 
             } finally {
                 readerCleanup();        // Clear reader thread
+
+                if (isBlocking()) {
+                    IoTrace.socketReadEnd(traceContext, n > 0 ? n : 0);
+                }
+
                 // The end method, which is defined in our superclass
                 // AbstractInterruptibleChannel, resets the interruption
                 // machinery.  If its argument is true then it returns
@@ -407,6 +417,11 @@
             if (!ensureReadOpen())
                 return -1;
             long n = 0;
+            Object traceContext = null;
+            if (isBlocking()) {
+                traceContext = IoTrace.socketReadBegin(remoteAddress.getAddress(),
+                                                      remoteAddress.getPort(), 0);
+            }
             try {
                 begin();
                 synchronized (stateLock) {
@@ -423,6 +438,9 @@
                 }
             } finally {
                 readerCleanup();
+                if (isBlocking()) {
+                    IoTrace.socketReadEnd(traceContext, n > 0 ? n : 0);
+                }
                 end(n > 0 || (n == IOStatus.UNAVAILABLE));
                 synchronized (stateLock) {
                     if ((n <= 0) && (!isInputOpen))
@@ -439,6 +457,10 @@
         synchronized (writeLock) {
             ensureWriteOpen();
             int n = 0;
+            Object traceContext =
+                IoTrace.socketWriteBegin(remoteAddress.getAddress(),
+                                         remoteAddress.getPort());
+
             try {
                 begin();
                 synchronized (stateLock) {
@@ -454,6 +476,7 @@
                 }
             } finally {
                 writerCleanup();
+                IoTrace.socketWriteEnd(traceContext, n > 0 ? n : 0);
                 end(n > 0 || (n == IOStatus.UNAVAILABLE));
                 synchronized (stateLock) {
                     if ((n <= 0) && (!isOutputOpen))
@@ -472,6 +495,9 @@
         synchronized (writeLock) {
             ensureWriteOpen();
             long n = 0;
+            Object traceContext =
+                IoTrace.socketWriteBegin(remoteAddress.getAddress(),
+                                         remoteAddress.getPort());
             try {
                 begin();
                 synchronized (stateLock) {
@@ -487,6 +513,7 @@
                 }
             } finally {
                 writerCleanup();
+                IoTrace.socketWriteEnd(traceContext, n > 0 ? n : 0);
                 end((n > 0) || (n == IOStatus.UNAVAILABLE));
                 synchronized (stateLock) {
                     if ((n <= 0) && (!isOutputOpen))
--- a/src/share/native/java/io/FileInputStream.c	Fri Jun 24 19:30:39 2011 +0100
+++ b/src/share/native/java/io/FileInputStream.c	Tue Nov 27 09:23:54 2012 +0100
@@ -62,7 +62,7 @@
 }
 
 JNIEXPORT jint JNICALL
-Java_java_io_FileInputStream_read(JNIEnv *env, jobject this) {
+Java_java_io_FileInputStream_read0(JNIEnv *env, jobject this) {
     return readSingle(env, this, fis_fd);
 }
 
--- a/src/share/native/java/io/RandomAccessFile.c	Fri Jun 24 19:30:39 2011 +0100
+++ b/src/share/native/java/io/RandomAccessFile.c	Tue Nov 27 09:23:54 2012 +0100
@@ -64,23 +64,23 @@
 }
 
 JNIEXPORT jint JNICALL
-Java_java_io_RandomAccessFile_read(JNIEnv *env, jobject this) {
+Java_java_io_RandomAccessFile_read0(JNIEnv *env, jobject this) {
     return readSingle(env, this, raf_fd);
 }
 
 JNIEXPORT jint JNICALL
-Java_java_io_RandomAccessFile_readBytes(JNIEnv *env,
+Java_java_io_RandomAccessFile_readBytes0(JNIEnv *env,
     jobject this, jbyteArray bytes, jint off, jint len) {
     return readBytes(env, this, bytes, off, len, raf_fd);
 }
 
 JNIEXPORT void JNICALL
-Java_java_io_RandomAccessFile_write(JNIEnv *env, jobject this, jint byte) {
+Java_java_io_RandomAccessFile_write0(JNIEnv *env, jobject this, jint byte) {
     writeSingle(env, this, byte, JNI_FALSE, raf_fd);
 }
 
 JNIEXPORT void JNICALL
-Java_java_io_RandomAccessFile_writeBytes(JNIEnv *env,
+Java_java_io_RandomAccessFile_writeBytes0(JNIEnv *env,
     jobject this, jbyteArray bytes, jint off, jint len) {
     writeBytes(env, this, bytes, off, len, JNI_FALSE, raf_fd);
 }
--- a/src/solaris/classes/sun/nio/fs/SolarisUserDefinedFileAttributeView.java	Fri Jun 24 19:30:39 2011 +0100
+++ b/src/solaris/classes/sun/nio/fs/SolarisUserDefinedFileAttributeView.java	Tue Nov 27 09:23:54 2012 +0100
@@ -147,7 +147,7 @@
                 int afd = openat(fd, nameAsBytes(file,name), (O_RDONLY|O_XATTR), 0);
 
                 // wrap with channel
-                FileChannel fc = UnixChannelFactory.newFileChannel(afd, true, false);
+                FileChannel fc = UnixChannelFactory.newFileChannel(afd, file.toString(), true, false);
 
                 // read to EOF (nothing we can do if I/O error occurs)
                 try {
@@ -188,7 +188,7 @@
                                  UnixFileModeAttribute.ALL_PERMISSIONS);
 
                 // wrap with channel
-                FileChannel fc = UnixChannelFactory.newFileChannel(afd, false, true);
+                FileChannel fc = UnixChannelFactory.newFileChannel(afd, file.toString(), false, true);
 
                 // write value (nothing we can do if I/O error occurs)
                 try {
--- a/src/solaris/classes/sun/nio/fs/UnixChannelFactory.java	Fri Jun 24 19:30:39 2011 +0100
+++ b/src/solaris/classes/sun/nio/fs/UnixChannelFactory.java	Tue Nov 27 09:23:54 2012 +0100
@@ -100,10 +100,10 @@
     /**
      * Constructs a file channel from an existing (open) file descriptor
      */
-    static FileChannel newFileChannel(int fd, boolean reading, boolean writing) {
+    static FileChannel newFileChannel(int fd, String path, boolean reading, boolean writing) {
         FileDescriptor fdObj = new FileDescriptor();
         fdAccess.set(fdObj, fd);
-        return FileChannelImpl.open(fdObj, reading, writing, null);
+        return FileChannelImpl.open(fdObj, path, reading, writing, null);
     }
 
     /**
@@ -134,7 +134,8 @@
             throw new IllegalArgumentException("APPEND + TRUNCATE_EXISTING not allowed");
 
         FileDescriptor fdObj = open(dfd, path, pathForPermissionCheck, flags, mode);
-        return FileChannelImpl.open(fdObj, flags.read, flags.write, flags.append, null);
+        return FileChannelImpl.open(fdObj, path.toString(),
+            flags.read, flags.write, flags.append, null);
     }
 
     /**
--- a/src/windows/classes/sun/nio/fs/WindowsChannelFactory.java	Fri Jun 24 19:30:39 2011 +0100
+++ b/src/windows/classes/sun/nio/fs/WindowsChannelFactory.java	Tue Nov 27 09:23:54 2012 +0100
@@ -157,7 +157,7 @@
             throw new IllegalArgumentException("APPEND + TRUNCATE_EXISTING not allowed");
 
         FileDescriptor fdObj = open(pathForWindows, pathToCheck, flags, pSecurityDescriptor);
-        return FileChannelImpl.open(fdObj, flags.read, flags.write, flags.append, null);
+        return FileChannelImpl.open(fdObj, pathForWindows, flags.read, flags.write, flags.append, null);
     }
 
     /**
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/misc/IoTrace/IoTraceAgent.java	Tue Nov 27 09:23:54 2012 +0100
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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.
+ */
+
+import static com.sun.xml.internal.ws.org.objectweb.asm.Opcodes.ACC_FINAL;
+import static com.sun.xml.internal.ws.org.objectweb.asm.Opcodes.ACC_PRIVATE;
+import static com.sun.xml.internal.ws.org.objectweb.asm.Opcodes.ACC_PUBLIC;
+import static com.sun.xml.internal.ws.org.objectweb.asm.Opcodes.ACC_STATIC;
+import static com.sun.xml.internal.ws.org.objectweb.asm.Opcodes.ACC_SUPER;
+import static com.sun.xml.internal.ws.org.objectweb.asm.Opcodes.ILOAD;
+import static com.sun.xml.internal.ws.org.objectweb.asm.Opcodes.INVOKESPECIAL;
+import static com.sun.xml.internal.ws.org.objectweb.asm.Opcodes.INVOKESTATIC;
+import static com.sun.xml.internal.ws.org.objectweb.asm.Opcodes.IRETURN;
+import static com.sun.xml.internal.ws.org.objectweb.asm.Opcodes.RETURN;
+import static com.sun.xml.internal.ws.org.objectweb.asm.Opcodes.V1_6;
+
+import java.lang.instrument.ClassDefinition;
+import java.lang.instrument.Instrumentation;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.net.InetAddress;
+
+import com.sun.xml.internal.ws.org.objectweb.asm.ClassWriter;
+import com.sun.xml.internal.ws.org.objectweb.asm.MethodVisitor;
+import com.sun.xml.internal.ws.org.objectweb.asm.Type;
+import sun.misc.IoTrace;
+
+public class IoTraceAgent {
+
+    private static IoTraceListener listener;
+
+    public static void setListener(IoTraceListener l) {
+        listener = l;
+    }
+
+    public static Object socketReadBegin(InetAddress address, int port,
+            int timeout) {
+        IoTraceListener l = listener;
+        if (l != null) {
+            return l.socketReadBegin(address, port, timeout);
+        }
+        return null;
+    }
+
+    public static void socketReadEnd(Object context, long bytesRead) {
+        IoTraceListener l = listener;
+        if (l != null) {
+            l.socketReadEnd(context, bytesRead);
+        }
+    }
+
+    public static Object socketWriteBegin(InetAddress address, int port) {
+        IoTraceListener l = listener;
+        if (l != null) {
+            return l.socketWriteBegin(address, port);
+        }
+        return null;
+    }
+
+    public static void socketWriteEnd(Object context, long bytesWritten) {
+        IoTraceListener l = listener;
+        if (l != null) {
+            l.socketWriteEnd(context, bytesWritten);
+        }
+    }
+
+    public static Object fileReadBegin(String path) {
+        IoTraceListener l = listener;
+        if (l != null) {
+            return l.fileReadBegin(path);
+        }
+        return null;
+    }
+
+    public static void fileReadEnd(Object context, long bytesRead) {
+        IoTraceListener l = listener;
+        if (l != null) {
+            l.fileReadEnd(context, bytesRead);
+        }
+    }
+
+    public static Object fileWriteBegin(String path) {
+        IoTraceListener l = listener;
+        if (l != null) {
+            return l.fileWriteBegin(path);
+        }
+        return null;
+    }
+
+    public static void fileWriteEnd(Object context, long bytesWritten) {
+        IoTraceListener l = listener;
+        if (l != null) {
+            l.fileWriteEnd(context, bytesWritten);
+        }
+    }
+
+    public static void premain(String agentArgs, Instrumentation inst)
+            throws Exception {
+        ClassDefinition cd = new ClassDefinition(IoTrace.class,
+                generateClassAsm());
+        inst.redefineClasses(cd);
+    }
+
+    private static byte[] generateClassAsm() {
+        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
+        cw.visit(V1_6, ACC_PUBLIC | ACC_SUPER | ACC_FINAL, "sun/misc/IoTrace",
+                null, "java/lang/Object", null);
+
+        // for all methods in the existing IoTrace class
+        // we want to create a method in the new version of it which call
+        // IoTraceAgent
+        //
+        // 0: aload_0
+        // 1: iload_1
+        // 2: iload_2
+        // 3: invokestatic #16 // Method
+        // IoTraceAgent.socketReadBegin:(Ljava/net/InetAddress;II)Ljava/lang/Object;
+        // 6: areturn
+
+        for (Method om : IoTrace.class.getDeclaredMethods()) {
+            if (!Modifier.isStatic(om.getModifiers())) {
+                continue;
+            }
+
+            // create a method with the same signature as the
+            // original method
+            MethodVisitor mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC,
+                    om.getName(), Type.getMethodDescriptor(om), null, null);
+            mv.visitCode();
+
+            // get the return type and argument list types
+            Type[] argTypes = Type.getArgumentTypes(om);
+            Type retType = Type.getReturnType(om);
+
+            // load all the arguments
+            int i = 0;
+            for (Type t : argTypes) {
+                mv.visitVarInsn(t.getOpcode(ILOAD), i++);
+            }
+
+            // call a method with the same signature (but in a different class)
+            // with all the arguments
+            mv.visitMethodInsn(INVOKESTATIC, "IoTraceAgent", om.getName(),
+                    Type.getMethodDescriptor(om));
+
+            // return the value from the called method
+            mv.visitInsn(retType.getOpcode(IRETURN));
+            mv.visitEnd();
+        }
+
+        // empty private constructor
+        MethodVisitor mv = cw.visitMethod(ACC_PRIVATE, "<init>", "()V", null,
+                null);
+        mv.visitCode();
+        mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
+        mv.visitInsn(RETURN);
+        mv.visitEnd();
+
+        cw.visitEnd();
+        return cw.toByteArray();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/misc/IoTrace/IoTraceBase.java	Tue Nov 27 09:23:54 2012 +0100
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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.
+ */
+
+import java.io.File;
+import java.net.InetAddress;
+
+
+public class IoTraceBase implements IoTraceListener {
+
+    protected static final Object my_context = new Object() {
+    };
+
+    private String path;
+    private long bytesRead;
+    private long bytesWritten;
+    private Object context;
+    private InetAddress address;
+    private int port;
+    private int timeout;
+
+    protected void clear() {
+        context = null;
+        bytesRead = 0;
+        bytesWritten = 0;
+        address = null;
+        port = 0;
+        timeout = 0;
+        path = null;
+    }
+
+    @Override
+    public Object fileWriteBegin(String p) {
+        path = p;
+        return my_context;
+    }
+
+    @Override
+    public void fileWriteEnd(Object ctx, long bw) {
+        context = ctx;
+        bytesWritten = bw;
+    }
+
+    @Override
+    public Object fileReadBegin(String p) {
+        path = p;
+        return my_context;
+    }
+
+    @Override
+    public void fileReadEnd(Object ctx, long br) {
+        context = ctx;
+        bytesRead = br;
+    }
+
+    @Override
+    public Object socketReadBegin(InetAddress address, int port,
+            int timeout) {
+        this.address = address;
+        this.port = port;
+        this.timeout = timeout;
+        return my_context;
+    }
+
+    @Override
+    public void socketReadEnd(Object context, long bytesRead) {
+        this.context = context;
+        this.bytesRead = bytesRead;
+    }
+
+    @Override
+    public Object socketWriteBegin(InetAddress address, int port) {
+        this.address = address;
+        this.port = port;
+        return my_context;
+    }
+
+    @Override
+    public void socketWriteEnd(Object context, long bytesWritten) {
+        this.context = context;
+        this.bytesWritten = bytesWritten;
+    }
+
+    protected void expectFileRead(long br, File f) throws Exception {
+        expectFile(0, br, f);
+    }
+
+    protected void expectFileWrite(long bw, File f) throws Exception {
+        expectFile(bw, 0, f);
+    }
+
+    protected void expectFile(long bw, long br, File f) throws Exception {
+        if (context != my_context) {
+            throw new Exception("Wrong context: " + context);
+        }
+        if (bytesWritten != bw) {
+            throw new Exception("Expected " + bw + " byte to be read, got: "
+                    + bytesWritten);
+        }
+        if (bytesRead != br) {
+            throw new Exception("Expected " + br + " byte to be read, got: "
+                    + bytesWritten);
+        }
+        if (!path.equals(f.getPath())) {
+            throw new Exception("Incorrect path: " + path + ". Expected: "
+                    + f.getPath());
+        }
+    }
+
+    protected void expectSocket(int br, int bw, InetAddress ia, int p, int t)
+            throws Exception {
+        if (context != my_context) {
+            throw new Exception("Wrong context: " + context);
+        }
+        if (bytesWritten != bw) {
+            throw new Exception("Expected " + bw + " byte to be written, got: "
+                    + bytesWritten);
+        }
+        if (bytesRead != br) {
+            throw new Exception("Expected " + br + " byte to be read, got: "
+                    + bytesWritten);
+        }
+        if (!address.equals(ia)) {
+            throw new Exception("Incorrect address: " + address
+                    + ". Expected: " + ia);
+        }
+        if (port != p) {
+            throw new Exception("Expected " + p + " port, got: " + port);
+        }
+        if (timeout != t) {
+            throw new Exception("Expected " + t + " timeout, got: " + timeout);
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/misc/IoTrace/IoTraceFileChannelReadWrite.java	Tue Nov 27 09:23:54 2012 +0100
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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.
+ */
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
+import java.nio.file.StandardOpenOption;
+
+/*
+ * @test
+ * @bug 8003322
+ * @run shell ioTraceTest.sh IoTraceFileChannelReadWrite
+ */
+public class IoTraceFileChannelReadWrite extends IoTraceBase {
+
+    private void testWrite(File f) throws IOException, FileNotFoundException,
+            Exception {
+        try (FileChannel fc = FileChannel.open(f.toPath(),
+                StandardOpenOption.WRITE)) {
+            ByteBuffer bb = ByteBuffer.allocate(1);
+            bb.put((byte) 11);
+            bb.flip();
+            fc.write(bb);
+        }
+        expectFile(1, 0, f);
+    }
+
+    private void testRead(File f) throws IOException, FileNotFoundException,
+            Exception {
+        try (FileChannel fc = FileChannel.open(f.toPath(),
+                StandardOpenOption.READ)) {
+            ByteBuffer bb = ByteBuffer.allocate(1);
+            fc.read(bb);
+        }
+        expectFile(0, 1, f);
+    }
+
+    public void test() throws Exception {
+        IoTraceAgent.setListener(this);
+        File f = File.createTempFile("IoTraceFileChannelReadWrite", ".bin");
+        try {
+            clear();
+            testWrite(f);
+            clear();
+            testRead(f);
+        } finally {
+            f.delete();
+        }
+    }
+
+    public static void main(String... args) throws Exception {
+        IoTraceFileChannelReadWrite t = new IoTraceFileChannelReadWrite();
+        t.test();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/misc/IoTrace/IoTraceFileReadWrite.java	Tue Nov 27 09:23:54 2012 +0100
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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.
+ */
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+
+/*
+ * @test
+ * @bug 8003322
+ * @run shell ioTraceTest.sh IoTraceFileReadWrite
+ */
+public class IoTraceFileReadWrite extends IoTraceBase {
+
+    private void testWrite(File f) throws IOException, FileNotFoundException,
+            Exception {
+        try (FileOutputStream fos = new FileOutputStream(f)) {
+            fos.write(11);
+        }
+        expectFile(1, 0, f);
+    }
+
+
+    private void testRead(File f) throws IOException, FileNotFoundException,
+            Exception {
+        try (FileInputStream fos = new FileInputStream(f)) {
+            fos.read();
+        }
+        expectFile(0, 1, f);
+    }
+
+    private void testRandomAccessWrite(File f) throws Exception {
+        try (RandomAccessFile raf = new RandomAccessFile(f, "rw")) {
+            raf.write(11);
+        }
+        expectFile(1, 0, f);
+    }
+
+    private void testRandomAccessRead(File f) throws Exception {
+        try (RandomAccessFile raf = new RandomAccessFile(f, "r")) {
+            raf.read();
+        }
+        expectFile(0, 1, f);
+    }
+
+    public void test() throws Exception {
+        IoTraceAgent.setListener(this);
+        File f = File.createTempFile("IoTraceFileReadWrite", ".bin");
+        try {
+            clear();
+            testWrite(f);
+            clear();
+            testRead(f);
+            clear();
+            testRandomAccessWrite(f);
+            clear();
+            testRandomAccessRead(f);
+        } finally {
+            f.delete();
+        }
+    }
+
+    public static void main(String... args) throws Exception {
+        IoTraceFileReadWrite t = new IoTraceFileReadWrite();
+        t.test();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/misc/IoTrace/IoTraceListener.java	Tue Nov 27 09:23:54 2012 +0100
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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.
+ */
+
+import java.net.InetAddress;
+
+import sun.misc.IoTrace;
+
+/**
+ * Implementations of this interface can be registered with
+ * {@link IoTrace#setListener(IoTraceListener)} to receive callbacks when file
+ * and socket operations are performed.
+ * <p>
+ * The xxBegin() methods return a "context". This can be any Object. This
+ * context will be passed to the corresponding xxEnd() method. This way, an
+ * implementation can correlate the beginning of an operation with the end.
+ * <p>
+ * It is possible for a xxEnd() method to be called with a null handle. This
+ * happens if tracing was started between the call to xxBegin() and xxEnd(), in
+ * which case xxBegin() would not have been called. It is the implementation's
+ * responsibility to not throw an exception in this case.
+ * <p>
+ * Implementations should never throw exceptions since this will cause
+ * disruptions to the I/O operations.
+ * <p>
+ * An xxBegin() call is not guaranteed to be followed by an xxEnd() call, since
+ * the listener in IoTrace can be reset at any time.
+ */
+public interface IoTraceListener {
+
+    /**
+     * Called before data is read from a socket.
+     *
+     * @param address
+     *            the remote address the socket is bound to
+     * @param port
+     *            the remote port the socket is bound to
+     * @param timeout
+     *            the SO_TIMEOUT value of the socket (in milliseconds) or 0 if
+     *            there is no timeout set
+     * @return a context object
+     */
+    public Object socketReadBegin(InetAddress address, int port, int timeout);
+
+    /**
+     * Called after data is read from the socket.
+     *
+     * @param context
+     *            the context returned by the previous call to socketReadBegin()
+     * @param bytesRead
+     *            the number of bytes read from the socket, 0 if there was an
+     *            error reading from the socket
+     */
+    public void socketReadEnd(Object context, long bytesRead);
+
+    /**
+     * Called before data is written to a socket.
+     *
+     * @param address
+     *            the remote address the socket is bound to
+     * @param port
+     *            the remote port the socket is bound to
+     * @return a context object
+     */
+    public Object socketWriteBegin(InetAddress address, int port);
+
+    /**
+     * Called after data is written to a socket.
+     *
+     * @param context
+     *            the context returned by the previous call to
+     *            socketWriteBegin()
+     * @param bytesWritten
+     *            the number of bytes written to the socket, 0 if there was an
+     *            error writing to the socket
+     */
+    public void socketWriteEnd(Object context, long bytesWritten);
+
+    /**
+     * Called before data is read from a file.
+     *
+     * @param path
+     *            the path of the file
+     * @return a context object
+     */
+    public Object fileReadBegin(String path);
+
+    /**
+     * Called after data is read from a file.
+     *
+     * @param context
+     *            the context returned by the previous call to fileReadBegin()
+     * @param bytesRead
+     *            the number of bytes written to the file, 0 if there was an
+     *            error writing to the file
+     */
+    public void fileReadEnd(Object context, long bytesRead);
+
+    /**
+     * Called before data is written to a file.
+     *
+     * @param path
+     *            the path of the file
+     * @return a context object
+     */
+    public Object fileWriteBegin(String path);
+
+    /**
+     * Called after data is written to a file.
+     *
+     * @param context
+     *            the context returned by the previous call to fileReadBegin()
+     * @param bytesWritten
+     *            the number of bytes written to the file, 0 if there was an
+     *            error writing to the file
+     */
+    public void fileWriteEnd(Object context, long bytesWritten);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/misc/IoTrace/IoTraceSocketReadWrite.java	Tue Nov 27 09:23:54 2012 +0100
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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.
+ */
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.InetAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+
+/*
+ * @test
+ * @bug 8003322
+ * @run shell ioTraceTest.sh IoTraceSocketReadWrite
+ */
+public class IoTraceSocketReadWrite extends IoTraceBase {
+
+    public void test() throws Exception {
+        IoTraceAgent.setListener(this);
+
+        ServerSocket ss = null;
+        Socket s1 = null, s2 = null;
+        OutputStream os = null;
+        InputStream is = null;
+
+        try {
+            InetAddress iaddr = InetAddress.getLocalHost();
+            ss = new ServerSocket(0);
+            s1 = new Socket(iaddr, ss.getLocalPort());
+            s2 = ss.accept();
+
+            os = s1.getOutputStream();
+            is = s2.getInputStream();
+
+            os.write((byte) 11);
+            is.read();
+
+            expectSocket(1, 1, s2.getInetAddress(), s2.getPort(), 0);
+
+        } finally {
+            if (ss != null) {
+                ss.close();
+            }
+            if (s1 != null) {
+                s1.close();
+            }
+            if (s2 != null) {
+                s2.close();
+            }
+        }
+    }
+
+    public static void main(String... args) throws Exception {
+        IoTraceSocketReadWrite t = new IoTraceSocketReadWrite();
+        t.test();
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/misc/IoTrace/ioTraceTest.sh	Tue Nov 27 09:23:54 2012 +0100
@@ -0,0 +1,34 @@
+#
+# Copyright (c) 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.
+#
+# 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.
+#
+
+set -x
+PWD=`pwd`
+
+cd ${TESTSRC}
+${TESTJAVA}/bin/javac -XDignore.symbol.file=true -d ${TESTCLASSES} *.java
+
+cd ${TESTCLASSES}
+${TESTJAVA}/bin/jar cfm iotraceagent.jar ${TESTSRC}/iotraceagent.mf IoTraceAgent.class IoTraceListener.class
+
+cd ${PWD}
+${TESTJAVA}/bin/java ${TESTVMOPTS} -javaagent:${TESTCLASSES}/iotraceagent.jar -cp ${TESTCLASSES} $*
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/misc/IoTrace/iotraceagent.mf	Tue Nov 27 09:23:54 2012 +0100
@@ -0,0 +1,3 @@
+Premain-Class: IoTraceAgent
+Can-Redefine-Classes: true
+Boot-Class-Path: iotraceagent.jar