--- old/make/java/java/mapfile-vers 2012-11-13 10:47:43.000000000 +0100 +++ new/make/java/java/mapfile-vers 2012-11-13 10:47:42.000000000 +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; @@ -98,12 +98,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; --- old/makefiles/mapfiles/libjava/mapfile-vers 2012-11-13 10:47:45.000000000 +0100 +++ new/makefiles/mapfiles/libjava/mapfile-vers 2012-11-13 10:47:45.000000000 +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; @@ -98,12 +98,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; --- old/src/share/classes/java/io/FileInputStream.java 2012-11-13 10:47:48.000000000 +0100 +++ new/src/share/classes/java/io/FileInputStream.java 2012-11-13 10:47:47.000000000 +0100 @@ -27,6 +27,8 @@ import java.nio.channels.FileChannel; import sun.nio.ch.FileChannelImpl; +import sun.misc.IoTrace; +import sun.misc.IoTraceContext; /** @@ -51,6 +53,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(); @@ -125,6 +130,7 @@ } fd = new FileDescriptor(); fd.attach(this); + this.path = name; open(name); } @@ -161,6 +167,7 @@ security.checkRead(fdObj); } fd = fdObj; + path = null; /* * FileDescriptor is being shared by streams. @@ -183,7 +190,18 @@ * file is reached. * @exception IOException if an I/O error occurs. */ - public native int read() throws IOException; + public int read() throws IOException { + IoTraceContext 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. @@ -206,7 +224,14 @@ * @exception IOException if an I/O error occurs. */ public int read(byte b[]) throws IOException { - return readBytes(b, 0, b.length); + IoTraceContext traceContext = IoTrace.fileReadBegin(path); + int bytesRead = 0; + try { + bytesRead = readBytes(b, 0, b.length); + } finally { + IoTrace.fileReadEnd(traceContext, bytesRead); + } + return bytesRead; } /** @@ -228,7 +253,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); + IoTraceContext traceContext = IoTrace.fileReadBegin(path); + int bytesRead = 0; + try { + bytesRead = readBytes(b, off, len); + } finally { + IoTrace.fileReadEnd(traceContext, bytesRead); + } + return bytesRead; } /** @@ -339,7 +371,7 @@ public FileChannel getChannel() { synchronized (this) { if (channel == null) { - channel = FileChannelImpl.open(fd, true, false, this); + channel = FileChannelImpl.open(fd, path, true, false, this); } return channel; } --- old/src/share/classes/java/io/FileOutputStream.java 2012-11-13 10:47:50.000000000 +0100 +++ new/src/share/classes/java/io/FileOutputStream.java 2012-11-13 10:47:49.000000000 +0100 @@ -27,6 +27,8 @@ import java.nio.channels.FileChannel; import sun.nio.ch.FileChannelImpl; +import sun.misc.IoTrace; +import sun.misc.IoTraceContext; /** @@ -58,6 +60,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; @@ -199,7 +206,7 @@ this.fd = new FileDescriptor(); fd.attach(this); this.append = append; - + this.path = name; open(name, append); } @@ -235,6 +242,7 @@ security.checkWrite(fdObj); } this.fd = fdObj; + this.path = null; this.append = false; fd.attach(this); @@ -265,7 +273,14 @@ * @exception IOException if an I/O error occurs. */ public void write(int b) throws IOException { - write(b, append); + IoTraceContext traceContext = IoTrace.fileWriteBegin(path); + int bytesWritten = 0; + try { + write(b, append); + bytesWritten = 1; + } finally { + IoTrace.fileWriteEnd(traceContext, bytesWritten); + } } /** @@ -288,7 +303,14 @@ * @exception IOException if an I/O error occurs. */ public void write(byte b[]) throws IOException { - writeBytes(b, 0, b.length, append); + IoTraceContext traceContext = IoTrace.fileWriteBegin(path); + int bytesWritten = 0; + try { + writeBytes(b, 0, b.length, append); + bytesWritten = b.length; + } finally { + IoTrace.fileWriteEnd(traceContext, bytesWritten); + } } /** @@ -301,7 +323,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); + IoTraceContext traceContext = IoTrace.fileWriteBegin(path); + int bytesWritten = 0; + try { + writeBytes(b, off, len, append); + bytesWritten = len; + } finally { + IoTrace.fileWriteEnd(traceContext, bytesWritten); + } } /** @@ -373,7 +402,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); } return channel; } --- old/src/share/classes/java/io/RandomAccessFile.java 2012-11-13 10:47:52.000000000 +0100 +++ new/src/share/classes/java/io/RandomAccessFile.java 2012-11-13 10:47:52.000000000 +0100 @@ -27,6 +27,8 @@ import java.nio.channels.FileChannel; import sun.nio.ch.FileChannelImpl; +import sun.misc.IoTrace; +import sun.misc.IoTraceContext; /** @@ -61,6 +63,7 @@ private FileDescriptor fd; private FileChannel channel = null; private boolean rw; + private final String path; private Object closeLock = new Object(); private volatile boolean closed = false; @@ -230,6 +233,7 @@ } fd = new FileDescriptor(); fd.attach(this); + this.path = name; open(name, imode); } @@ -269,7 +273,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); } return channel; } @@ -306,7 +310,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 { + IoTraceContext traceContext = IoTrace.fileReadBegin(path); + int v = 0; + try { + v = read0(); + } finally { + IoTrace.fileReadEnd(traceContext, v == -1 ? 0 : 1); + } + return v; + } + + private native int read0() throws IOException; /** * Reads a sub array as a sequence of bytes. @@ -315,7 +330,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 { + IoTraceContext traceContext = IoTrace.fileReadBegin(path); + int v = 0; + try { + v = readBytes0(b, off, len); + } finally { + IoTrace.fileReadEnd(traceContext, v); + } + return v; + } + + private native int readBytes0(byte b[], int off, int len) throws IOException; /** * Reads up to {@code len} bytes of data from this file into an @@ -454,17 +480,38 @@ * @param b the {@code byte} 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 { + IoTraceContext traceContext = IoTrace.fileWriteBegin(path); + int v = 0; + try { + write0(b); + v = 1; + } finally { + IoTrace.fileWriteEnd(traceContext, v); + } + } + + 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 { + IoTraceContext traceContext = IoTrace.fileWriteBegin(path); + int v = 0; + try { + writeBytes0(b, off, len); + v = len; + } finally { + IoTrace.fileWriteEnd(traceContext, v); + } + } + + private native void writeBytes0(byte b[], int off, int len) throws IOException; /** * Writes {@code b.length} bytes from the specified byte array --- old/src/share/classes/java/net/SocketInputStream.java 2012-11-13 10:47:54.000000000 +0100 +++ new/src/share/classes/java/net/SocketInputStream.java 2012-11-13 10:47:54.000000000 +0100 @@ -30,6 +30,8 @@ import java.io.IOException; import java.nio.channels.FileChannel; +import sun.misc.IoTrace; +import sun.misc.IoTraceContext; import sun.net.ConnectionResetException; /** @@ -122,7 +124,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 +146,7 @@ boolean gotReset = false; + IoTraceContext traceContext = IoTrace.socketReadBegin(impl.address, impl.port, timeout); // acquire file descriptor and do the read FileDescriptor fd = impl.acquireFD(); try { @@ -155,6 +158,7 @@ gotReset = true; } finally { impl.releaseFD(); + IoTrace.socketReadEnd(traceContext, n > 0 ? n : 0); } /* @@ -162,6 +166,7 @@ * buffered on the socket */ if (gotReset) { + traceContext = IoTrace.socketReadBegin(impl.address, impl.port, timeout); impl.setConnectionResetPending(); impl.acquireFD(); try { @@ -172,6 +177,7 @@ } catch (ConnectionResetException rstExc) { } finally { impl.releaseFD(); + IoTrace.socketReadEnd(traceContext, n > 0 ? n : 0); } } --- old/src/share/classes/java/net/SocketOutputStream.java 2012-11-13 10:47:57.000000000 +0100 +++ new/src/share/classes/java/net/SocketOutputStream.java 2012-11-13 10:47:56.000000000 +0100 @@ -30,6 +30,9 @@ import java.io.IOException; import java.nio.channels.FileChannel; +import sun.misc.IoTrace; +import sun.misc.IoTraceContext; + /** * This stream extends FileOutputStream to implement a * SocketOutputStream. Note that this class should NOT be @@ -104,9 +107,12 @@ throw new ArrayIndexOutOfBoundsException(); } + IoTraceContext 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 +125,7 @@ } } finally { impl.releaseFD(); + IoTrace.socketWriteEnd(traceContext, bytesWritten); } } --- old/src/share/classes/sun/nio/ch/FileChannelImpl.java 2012-11-13 10:47:59.000000000 +0100 +++ new/src/share/classes/sun/nio/ch/FileChannelImpl.java 2012-11-13 10:47:58.000000000 +0100 @@ -34,6 +34,8 @@ import java.util.List; import java.security.AccessController; import sun.misc.Cleaner; +import sun.misc.IoTrace; +import sun.misc.IoTraceContext; import sun.security.action.GetPropertyAction; public class FileChannelImpl @@ -56,13 +58,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 +75,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 +140,7 @@ synchronized (positionLock) { int n = 0; int ti = -1; + IoTraceContext traceContext = IoTrace.fileReadBegin(path); try { begin(); ti = threads.add(); @@ -145,6 +152,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 +170,7 @@ synchronized (positionLock) { long n = 0; int ti = -1; + IoTraceContext traceContext = IoTrace.fileReadBegin(path); try { begin(); ti = threads.add(); @@ -173,6 +182,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 +196,7 @@ synchronized (positionLock) { int n = 0; int ti = -1; + IoTraceContext traceContext = IoTrace.fileWriteBegin(path); try { begin(); ti = threads.add(); @@ -198,6 +209,7 @@ } finally { threads.remove(ti); end(n > 0); + IoTrace.fileWriteEnd(traceContext, IOStatus.normalize(n)); assert IOStatus.check(n); } } @@ -214,6 +226,7 @@ synchronized (positionLock) { long n = 0; int ti = -1; + IoTraceContext traceContext = IoTrace.fileWriteBegin(path); try { begin(); ti = threads.add(); @@ -225,6 +238,7 @@ return IOStatus.normalize(n); } finally { threads.remove(ti); + IoTrace.fileWriteEnd(traceContext, n > 0 ? n : 0); end(n > 0); assert IOStatus.check(n); } @@ -673,6 +687,7 @@ ensureOpen(); int n = 0; int ti = -1; + IoTraceContext traceContext = IoTrace.fileReadBegin(path); try { begin(); ti = threads.add(); @@ -684,6 +699,7 @@ return IOStatus.normalize(n); } finally { threads.remove(ti); + IoTrace.fileReadEnd(traceContext, n > 0 ? n : 0); end(n > 0); assert IOStatus.check(n); } @@ -699,6 +715,7 @@ ensureOpen(); int n = 0; int ti = -1; + IoTraceContext traceContext = IoTrace.fileWriteBegin(path); try { begin(); ti = threads.add(); @@ -711,6 +728,7 @@ } finally { threads.remove(ti); end(n > 0); + IoTrace.fileWriteEnd(traceContext, IOStatus.normalize(n)); assert IOStatus.check(n); } } --- old/src/share/classes/sun/nio/ch/SocketAdaptor.java 2012-11-13 10:48:01.000000000 +0100 +++ new/src/share/classes/sun/nio/ch/SocketAdaptor.java 2012-11-13 10:48:01.000000000 +0100 @@ -34,6 +34,9 @@ import java.security.PrivilegedExceptionAction; import java.util.*; +import sun.misc.IoTrace; +import sun.misc.IoTraceContext; + // Make a socket channel look like a socket. // @@ -191,10 +194,12 @@ return sc.read(bb); sc.configureBlocking(false); + int n = 0; + IoTraceContext traceContext = IoTrace.socketReadBegin(getInetAddress(), getPort(), timeout); try { - int n; - if ((n = sc.read(bb)) != 0) + if ((n = sc.read(bb)) != 0) { return n; + } long to = timeout; for (;;) { if (!sc.isOpen()) @@ -210,6 +215,7 @@ throw new SocketTimeoutException(); } } finally { + IoTrace.socketReadEnd(traceContext, n > 0 ? n : 0); if (sc.isOpen()) sc.configureBlocking(true); } --- old/src/share/classes/sun/nio/ch/SocketChannelImpl.java 2012-11-13 10:48:03.000000000 +0100 +++ new/src/share/classes/sun/nio/ch/SocketChannelImpl.java 2012-11-13 10:48:03.000000000 +0100 @@ -33,7 +33,8 @@ import java.nio.channels.spi.*; import java.util.*; import sun.net.NetHooks; - +import sun.misc.IoTrace; +import sun.misc.IoTraceContext; /** * An implementation of SocketChannels @@ -80,8 +81,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 +279,11 @@ synchronized (readLock) { if (!ensureReadOpen()) return -1; + IoTraceContext traceContext = null; + if (isBlocking()) { + traceContext = IoTrace.socketReadBegin(remoteAddress.getAddress(), + remoteAddress.getPort(), 0); + } int n = 0; try { @@ -367,6 +373,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 +418,11 @@ if (!ensureReadOpen()) return -1; long n = 0; + IoTraceContext traceContext = null; + if (isBlocking()) { + traceContext = IoTrace.socketReadBegin(remoteAddress.getAddress(), + remoteAddress.getPort(), 0); + } try { begin(); synchronized (stateLock) { @@ -423,6 +439,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 +458,10 @@ synchronized (writeLock) { ensureWriteOpen(); int n = 0; + IoTraceContext traceContext = + IoTrace.socketWriteBegin(remoteAddress.getAddress(), + remoteAddress.getPort()); + try { begin(); synchronized (stateLock) { @@ -454,6 +477,7 @@ } } finally { writerCleanup(); + IoTrace.socketWriteEnd(traceContext, n > 0 ? n : 0); end(n > 0 || (n == IOStatus.UNAVAILABLE)); synchronized (stateLock) { if ((n <= 0) && (!isOutputOpen)) @@ -472,6 +496,9 @@ synchronized (writeLock) { ensureWriteOpen(); long n = 0; + IoTraceContext traceContext = + IoTrace.socketWriteBegin(remoteAddress.getAddress(), + remoteAddress.getPort()); try { begin(); synchronized (stateLock) { @@ -487,6 +514,7 @@ } } finally { writerCleanup(); + IoTrace.socketWriteEnd(traceContext, n > 0 ? n : 0); end((n > 0) || (n == IOStatus.UNAVAILABLE)); synchronized (stateLock) { if ((n <= 0) && (!isOutputOpen)) --- old/src/share/native/java/io/FileInputStream.c 2012-11-13 10:48:05.000000000 +0100 +++ new/src/share/native/java/io/FileInputStream.c 2012-11-13 10:48:05.000000000 +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); } --- old/src/share/native/java/io/RandomAccessFile.c 2012-11-13 10:48:07.000000000 +0100 +++ new/src/share/native/java/io/RandomAccessFile.c 2012-11-13 10:48:07.000000000 +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); } --- old/src/solaris/classes/sun/nio/fs/SolarisUserDefinedFileAttributeView.java 2012-11-13 10:48:10.000000000 +0100 +++ new/src/solaris/classes/sun/nio/fs/SolarisUserDefinedFileAttributeView.java 2012-11-13 10:48:09.000000000 +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 { --- old/src/solaris/classes/sun/nio/fs/UnixChannelFactory.java 2012-11-13 10:48:12.000000000 +0100 +++ new/src/solaris/classes/sun/nio/fs/UnixChannelFactory.java 2012-11-13 10:48:11.000000000 +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); } /** --- old/src/windows/classes/sun/nio/fs/WindowsChannelFactory.java 2012-11-13 10:48:14.000000000 +0100 +++ new/src/windows/classes/sun/nio/fs/WindowsChannelFactory.java 2012-11-13 10:48:13.000000000 +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 2012-11-13 10:48:16.000000000 +0100 +++ new/src/share/classes/sun/misc/IoTrace.java 2012-11-13 10:48:16.000000000 +0100 @@ -0,0 +1,161 @@ +/* + * 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. + *
+ * 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. + *
+ * The xxBegin() methods return a "context". This can be any Object marked with + * the {@link IoTraceContext} empty interface. This context will be passed to + * the corresponding xxEnd() method. This way, an implementation can correlate + * the beginning of an operation with the end. + *
+ * 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. + *
+ * Implementations must not throw exceptions since this will cause disruptions + * to the I/O operations. + *
+ * Implementations must not do I/O operations since this will lead to an endless + * loop. + *
+ * Only blocking I/O operations are identified with this facility.
+ */
+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 an IoTraceContext object
+ */
+ public static IoTraceContext 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(IoTraceContext 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 an IoTraceContext object
+ */
+ public static IoTraceContext 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(IoTraceContext context, long bytesWritten) {
+ }
+
+ /**
+ * Called before data is read from a file.
+ *
+ * @param path
+ * the path of the file
+ * @return an IoTraceContext object
+ */
+ public static IoTraceContext 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(IoTraceContext context, long bytesRead) {
+ }
+
+ /**
+ * Called before data is written to a file.
+ *
+ * @param path
+ * the path of the file
+ * @return an IoTraceContext object
+ */
+ public static IoTraceContext 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(IoTraceContext context, long bytesWritten) {
+ }
+}
--- /dev/null 2012-11-13 10:48:18.000000000 +0100
+++ new/src/share/classes/sun/misc/IoTraceContext.java 2012-11-13 10:48:18.000000000 +0100
@@ -0,0 +1,33 @@
+/*
+ * 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;
+
+/**
+ * This is an empty interface used to mark the "context" objects used in
+ * {@link IoTraceListener}.
+ */
+public interface IoTraceContext {
+}
--- /dev/null 2012-11-13 10:48:20.000000000 +0100
+++ new/test/sun/misc/IoTrace/IoTraceAgent.java 2012-11-13 10:48:20.000000000 +0100
@@ -0,0 +1,209 @@
+/*
+ * 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.
+ */
+
+import static jdk.internal.org.objectweb.asm.Opcodes.ACC_FINAL;
+import static jdk.internal.org.objectweb.asm.Opcodes.ACC_PRIVATE;
+import static jdk.internal.org.objectweb.asm.Opcodes.ACC_PUBLIC;
+import static jdk.internal.org.objectweb.asm.Opcodes.ACC_STATIC;
+import static jdk.internal.org.objectweb.asm.Opcodes.ACC_SUPER;
+import static jdk.internal.org.objectweb.asm.Opcodes.ALOAD;
+import static jdk.internal.org.objectweb.asm.Opcodes.ARETURN;
+import static jdk.internal.org.objectweb.asm.Opcodes.ILOAD;
+import static jdk.internal.org.objectweb.asm.Opcodes.INVOKESTATIC;
+import static jdk.internal.org.objectweb.asm.Opcodes.LLOAD;
+import static jdk.internal.org.objectweb.asm.Opcodes.RETURN;
+import static jdk.internal.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 jdk.internal.org.objectweb.asm.ClassWriter;
+import jdk.internal.org.objectweb.asm.MethodVisitor;
+import jdk.internal.org.objectweb.asm.Type;
+import sun.misc.IoTrace;
+import sun.misc.IoTraceContext;
+
+public class IoTraceAgent {
+
+ private static IoTraceListener listener;
+
+ public static void setListener(IoTraceListener l) {
+ listener = l;
+ }
+
+ public static IoTraceContext 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(IoTraceContext context, long bytesRead) {
+ IoTraceListener l = listener;
+ if (l != null) {
+ l.socketReadEnd(context, bytesRead);
+ }
+ }
+
+ public static IoTraceContext socketWriteBegin(InetAddress address, int port) {
+ IoTraceListener l = listener;
+ if (l != null) {
+ return l.socketWriteBegin(address, port);
+ }
+ return null;
+ }
+
+ public static void socketWriteEnd(IoTraceContext context, long bytesWritten) {
+ IoTraceListener l = listener;
+ if (l != null) {
+ l.socketWriteEnd(context, bytesWritten);
+ }
+ }
+
+ public static IoTraceContext fileReadBegin(String path) {
+ IoTraceListener l = listener;
+ if (l != null) {
+ return l.fileReadBegin(path);
+ }
+ return null;
+ }
+
+ public static void fileReadEnd(IoTraceContext context, long bytesRead) {
+ IoTraceListener l = listener;
+ if (l != null) {
+ l.fileReadEnd(context, bytesRead);
+ }
+ }
+
+ public static IoTraceContext fileWriteBegin(String path) {
+ IoTraceListener l = listener;
+ if (l != null) {
+ return l.fileWriteBegin(path);
+ }
+ return null;
+ }
+
+ public static void fileWriteEnd(IoTraceContext 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_FRAMES
+ | 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)Lsun/misc/IoTraceContext;
+ // 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) {
+ int instr;
+ switch (t.getSort()) {
+ case Type.INT:
+ instr = ILOAD;
+ break;
+ case Type.LONG:
+ instr = LLOAD;
+ break;
+ case Type.OBJECT:
+ instr = ALOAD;
+ break;
+ default:
+ throw new IllegalArgumentException(
+ "Unhandled argument type when generating code: "
+ + t);
+ }
+ mv.visitVarInsn(instr, 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
+ if (retType.getSort() == Type.VOID) {
+ mv.visitInsn(RETURN);
+ } else if (retType.getSort() == Type.OBJECT) {
+ mv.visitInsn(ARETURN);
+ } else {
+ throw new IllegalArgumentException(
+ "Unhandled return type when generating code: "
+ + retType);
+ }
+ mv.visitEnd();
+ }
+
+ // empty private constructor
+ MethodVisitor mv = cw.visitMethod(ACC_PRIVATE, "
+ * The xxBegin() methods return a "context". This can be any Object marked with
+ * the {@link IoTraceContext} empty interface. This context will be passed to
+ * the corresponding xxEnd() method. This way, an implementation can correlate
+ * the beginning of an operation with the end.
+ *
+ * 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.
+ *
+ * Implementations should never throw exceptions since this will cause
+ * disruptions to the I/O operations.
+ *
+ * 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 an IoTraceContext object
+ */
+ public IoTraceContext 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(IoTraceContext 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 an IoTraceContext object
+ */
+ public IoTraceContext 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(IoTraceContext context, long bytesWritten);
+
+ /**
+ * Called before data is read from a file.
+ *
+ * @param path
+ * the path of the file
+ * @return an IoTraceContext object
+ */
+ public IoTraceContext 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(IoTraceContext context, long bytesRead);
+
+ /**
+ * Called before data is written to a file.
+ *
+ * @param path
+ * the path of the file
+ * @return an IoTraceContext object
+ */
+ public IoTraceContext 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(IoTraceContext context, long bytesWritten);
+}
--- /dev/null 2012-11-13 10:48:33.000000000 +0100
+++ new/test/sun/misc/IoTrace/IoTraceSocketReadWrite.java 2012-11-13 10:48:32.000000000 +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. 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.
+ */
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.InetAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+
+/*
+ * @test
+ * @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 2012-11-13 10:48:35.000000000 +0100
+++ new/test/sun/misc/IoTrace/ioTraceTest.sh 2012-11-13 10:48:34.000000000 +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 FileRead.class
+
+cd ${PWD}
+${TESTJAVA}/bin/java ${TESTVMOPTS} -javaagent:${TESTCLASSES}/iotraceagent.jar -cp ${TESTCLASSES} $*
--- /dev/null 2012-11-13 10:48:37.000000000 +0100
+++ new/test/sun/misc/IoTrace/iotraceagent.mf 2012-11-13 10:48:36.000000000 +0100
@@ -0,0 +1,3 @@
+Premain-Class: IoTraceAgent
+Can-Redefine-Classes: true
+Boot-Class-Path: iotraceagent.jar