--- old/src/java.base/share/classes/java/io/FileInputStream.java 2016-08-25 17:51:52.487564684 -0700 +++ new/src/java.base/share/classes/java/io/FileInputStream.java 2016-08-25 17:51:52.384564683 -0700 @@ -62,6 +62,9 @@ private final AtomicBoolean closed = new AtomicBoolean(false); + private boolean direct = false; + + private int pageSize = -1; /** * Creates a FileInputStream by * opening a connection to an actual file, @@ -94,6 +97,41 @@ } /** + * Creates a FileInputStream by + * opening a connection to an actual file, + * the file named by the path name name + * in the file system. If the second parameter is + * true, bytes are directly read from + * storage media. A new FileDescriptor + * object is created to represent this file connection. + *

+ * First, if there is a security + * manager, its checkRead method + * is called with the name argument + * as its argument. + *

+ * If the named file does not exist, is a directory rather than a regular + * file, or for some other reason cannot be opened for reading then a + * FileNotFoundException is thrown. + * + * @param name the system-dependent file name. + * @param direct if true, then bytes will be read + * directly to storage media + * @exception FileNotFoundException if the file does not exist, + * is a directory rather than a regular file, + * or for some other reason cannot be opened for + * reading. + * @exception SecurityException if a security manager exists and its + * checkRead method denies read access + * to the file. + * @see java.lang.SecurityManager#checkRead(java.lang.String) + * @since 1.9 + */ + public FileInputStream(String name, boolean direct) throws FileNotFoundException { + this(name != null ? new File(name): null, direct); + } + + /** * Creates a FileInputStream by * opening a connection to an actual file, * the file named by the File @@ -121,21 +159,7 @@ * @see java.lang.SecurityManager#checkRead(java.lang.String) */ public FileInputStream(File file) throws FileNotFoundException { - String name = (file != null ? file.getPath() : null); - SecurityManager security = System.getSecurityManager(); - if (security != null) { - security.checkRead(name); - } - if (name == null) { - throw new NullPointerException(); - } - if (file.isInvalid()) { - throw new FileNotFoundException("Invalid file path"); - } - fd = new FileDescriptor(); - fd.attach(this); - path = name; - open(name); + this(file, false); } /** @@ -180,11 +204,54 @@ fd.attach(this); } + /** + * Creates a FileInputStream by opening a connection to an + * actual file with O_DIRECT option, the file named by the + * File object file in the file system. A new + * FileDescriptor object is created to represent this file connection. + *

+ * First, if there is a security manager, its checkRead + * method is called with the path represented by the file + * argument as its argument. + *

+ * If the named file does not exist, is a directory rather than a regular + * file, or for some other reason cannot be opened for reading then a + * FileNotFoundException is thrown. + * @param file the file to be opened for reading. + * @param direct if true, then bytes will be read + * directly to storage media + * @exception FileNotFoundException if the file does not exist, is a + * directory rather than a regular file, or for some + * other reason cannot be opened for reading. + * @exception SecurityException if a security manager exists + */ + public FileInputStream(File file, boolean direct) throws FileNotFoundException { + this.direct = direct; + if (direct) { + getPageSize(); + } + String name = (file != null ? file.getPath() : null); + SecurityManager security = System.getSecurityManager(); + if (security != null) { + security.checkRead(name); + } + if (name == null) { + throw new NullPointerException(); + } + if (file.isInvalid()) { + throw new FileNotFoundException("Invalid file path"); + } + fd = new FileDescriptor(); + fd.attach(this); + path = name; + open(name); + } + /** * Opens the specified file for reading. * @param name the name of the file */ - private native void open0(String name) throws FileNotFoundException; + private native void open0(String name, boolean direct) throws FileNotFoundException; // wrap native call to allow instrumentation /** @@ -192,7 +259,16 @@ * @param name the name of the file */ private void open(String name) throws FileNotFoundException { - open0(name); + open0(name, direct); + } + + private native int getPageSize0(); + + private int getPageSize() { + if (pageSize == -1) { + pageSize = getPageSize0(); + } + return this.pageSize; } /** @@ -219,6 +295,15 @@ private native int readBytes(byte b[], int off, int len) throws IOException; /** + * Reads a subarray as a sequence of bytes with DirectIO. + * @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 int readBytesD(byte b[], int off, int len) throws IOException; + + /** * Reads up to b.length bytes of data from this input * stream into an array of bytes. This method blocks until some input * is available. @@ -230,6 +315,8 @@ * @exception IOException if an I/O error occurs. */ public int read(byte b[]) throws IOException { + if (direct) + return readBytesD(b, 0, b.length); return readBytes(b, 0, b.length); } @@ -252,6 +339,8 @@ * @exception IOException if an I/O error occurs. */ public int read(byte b[], int off, int len) throws IOException { + if (direct) + return readBytesD(b, off, len); return readBytes(b, off, len); }