8154077: (fs) Reduce number of file system classes loaded during startup
authoralanb
Wed, 13 Apr 2016 14:29:25 +0100
changeset 37346 931e55c1287d
parent 37345 9cb6e1141bdb
child 37347 f6abe5d4bb1d
8154077: (fs) Reduce number of file system classes loaded during startup Reviewed-by: bpb, chegar
jdk/make/mapfiles/libnio/mapfile-linux
jdk/make/mapfiles/libnio/mapfile-macosx
jdk/make/mapfiles/libnio/mapfile-solaris
jdk/src/java.base/share/classes/java/nio/file/Files.java
jdk/src/java.base/share/classes/sun/nio/fs/AbstractFileSystemProvider.java
jdk/src/java.base/unix/classes/sun/nio/fs/UnixFileSystemProvider.java
jdk/src/java.base/unix/classes/sun/nio/fs/UnixNativeDispatcher.java
jdk/src/java.base/unix/classes/sun/nio/fs/UnixUriUtils.java
jdk/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c
--- a/jdk/make/mapfiles/libnio/mapfile-linux	Wed Apr 13 15:05:50 2016 +0200
+++ b/jdk/make/mapfiles/libnio/mapfile-linux	Wed Apr 13 14:29:25 2016 +0100
@@ -161,7 +161,9 @@
 		Java_sun_nio_fs_UnixNativeDispatcher_strerror;
 		Java_sun_nio_fs_UnixNativeDispatcher_dup;
 		Java_sun_nio_fs_UnixNativeDispatcher_access0;
+		Java_sun_nio_fs_UnixNativeDispatcher_exists0;
 		Java_sun_nio_fs_UnixNativeDispatcher_stat0;
+		Java_sun_nio_fs_UnixNativeDispatcher_stat1;
 		Java_sun_nio_fs_UnixNativeDispatcher_lstat0;
 		Java_sun_nio_fs_UnixNativeDispatcher_fstat;
 		Java_sun_nio_fs_UnixNativeDispatcher_fstatat0;
--- a/jdk/make/mapfiles/libnio/mapfile-macosx	Wed Apr 13 15:05:50 2016 +0200
+++ b/jdk/make/mapfiles/libnio/mapfile-macosx	Wed Apr 13 14:29:25 2016 +0100
@@ -138,7 +138,9 @@
 		Java_sun_nio_fs_UnixNativeDispatcher_strerror;
 		Java_sun_nio_fs_UnixNativeDispatcher_dup;
 		Java_sun_nio_fs_UnixNativeDispatcher_access0;
+		Java_sun_nio_fs_UnixNativeDispatcher_exists0;
 		Java_sun_nio_fs_UnixNativeDispatcher_stat0;
+                Java_sun_nio_fs_UnixNativeDispatcher_stat1;
 		Java_sun_nio_fs_UnixNativeDispatcher_lstat0;
 		Java_sun_nio_fs_UnixNativeDispatcher_fstat;
 		Java_sun_nio_fs_UnixNativeDispatcher_fstatat0;
--- a/jdk/make/mapfiles/libnio/mapfile-solaris	Wed Apr 13 15:05:50 2016 +0200
+++ b/jdk/make/mapfiles/libnio/mapfile-solaris	Wed Apr 13 14:29:25 2016 +0100
@@ -138,7 +138,9 @@
 		Java_sun_nio_fs_UnixNativeDispatcher_strerror;
 		Java_sun_nio_fs_UnixNativeDispatcher_dup;
 		Java_sun_nio_fs_UnixNativeDispatcher_access0;
+		Java_sun_nio_fs_UnixNativeDispatcher_exists0;
 		Java_sun_nio_fs_UnixNativeDispatcher_stat0;
+		Java_sun_nio_fs_UnixNativeDispatcher_stat1;
 		Java_sun_nio_fs_UnixNativeDispatcher_lstat0;
 		Java_sun_nio_fs_UnixNativeDispatcher_fstat;
 		Java_sun_nio_fs_UnixNativeDispatcher_fstatat0;
--- a/jdk/src/java.base/share/classes/java/nio/file/Files.java	Wed Apr 13 15:05:50 2016 +0200
+++ b/jdk/src/java.base/share/classes/java/nio/file/Files.java	Wed Apr 13 14:29:25 2016 +0100
@@ -77,6 +77,8 @@
 import java.util.stream.Stream;
 import java.util.stream.StreamSupport;
 
+import sun.nio.fs.AbstractFileSystemProvider;
+
 /**
  * This class consists exclusively of static methods that operate on files,
  * directories, or other types of files.
@@ -2193,6 +2195,12 @@
      *          method denies read access to the file.
      */
     public static boolean isDirectory(Path path, LinkOption... options) {
+        if (options.length == 0) {
+            FileSystemProvider provider = provider(path);
+            if (provider instanceof AbstractFileSystemProvider)
+                return ((AbstractFileSystemProvider)provider).isDirectory(path);
+        }
+
         try {
             return readAttributes(path, BasicFileAttributes.class, options).isDirectory();
         } catch (IOException ioe) {
@@ -2230,6 +2238,12 @@
      *          method denies read access to the file.
      */
     public static boolean isRegularFile(Path path, LinkOption... options) {
+        if (options.length == 0) {
+            FileSystemProvider provider = provider(path);
+            if (provider instanceof AbstractFileSystemProvider)
+                return ((AbstractFileSystemProvider)provider).isRegularFile(path);
+        }
+
         try {
             return readAttributes(path, BasicFileAttributes.class, options).isRegularFile();
         } catch (IOException ioe) {
@@ -2385,6 +2399,12 @@
      * @see #notExists
      */
     public static boolean exists(Path path, LinkOption... options) {
+        if (options.length == 0) {
+            FileSystemProvider provider = provider(path);
+            if (provider instanceof AbstractFileSystemProvider)
+                return ((AbstractFileSystemProvider)provider).exists(path);
+        }
+
         try {
             if (followLinks(options)) {
                 provider(path).checkAccess(path);
--- a/jdk/src/java.base/share/classes/sun/nio/fs/AbstractFileSystemProvider.java	Wed Apr 13 15:05:50 2016 +0200
+++ b/jdk/src/java.base/share/classes/sun/nio/fs/AbstractFileSystemProvider.java	Wed Apr 13 14:29:25 2016 +0100
@@ -25,7 +25,9 @@
 
 package sun.nio.fs;
 
-import java.nio.file.*;
+import java.nio.file.Path;
+import java.nio.file.LinkOption;
+import java.nio.file.attribute.BasicFileAttributes;
 import java.nio.file.spi.FileSystemProvider;
 import java.io.IOException;
 import java.util.Map;
@@ -34,7 +36,7 @@
  * Base implementation class of FileSystemProvider
  */
 
-abstract class AbstractFileSystemProvider extends FileSystemProvider {
+public abstract class AbstractFileSystemProvider extends FileSystemProvider {
     protected AbstractFileSystemProvider() { }
 
     /**
@@ -107,4 +109,49 @@
     public final boolean deleteIfExists(Path file) throws IOException {
         return implDelete(file, false);
     }
+
+    /**
+     * Tests whether a file is a directory.
+     *
+     * @return  {@code true} if the file is a directory; {@code false} if
+     *          the file does not exist, is not a directory, or it cannot
+     *          be determined if the file is a directory or not.
+     */
+    public boolean isDirectory(Path file) {
+        try {
+            return readAttributes(file, BasicFileAttributes.class).isDirectory();
+        } catch (IOException ioe) {
+            return false;
+        }
+    }
+
+    /**
+     * Tests whether a file is a regular file with opaque content.
+     *
+     * @return  {@code true} if the file is a regular file; {@code false} if
+     *          the file does not exist, is not a regular file, or it
+     *          cannot be determined if the file is a regular file or not.
+     */
+    public boolean isRegularFile(Path file) {
+        try {
+            return readAttributes(file, BasicFileAttributes.class).isRegularFile();
+        } catch (IOException ioe) {
+            return false;
+        }
+    }
+
+    /**
+     * Checks the existence of a file.
+     *
+     * @return  {@code true} if the file exists; {@code false} if the file does
+     *          not exist or its existence cannot be determined.
+     */
+    public boolean exists(Path file) {
+        try {
+            checkAccess(file);
+            return true;
+        } catch (IOException ioe) {
+            return false;
+        }
+    }
 }
--- a/jdk/src/java.base/unix/classes/sun/nio/fs/UnixFileSystemProvider.java	Wed Apr 13 15:05:50 2016 +0200
+++ b/jdk/src/java.base/unix/classes/sun/nio/fs/UnixFileSystemProvider.java	Wed Apr 13 14:29:25 2016 +0100
@@ -499,6 +499,29 @@
         }
     }
 
+    @Override
+    public final boolean isDirectory(Path obj) {
+        UnixPath file = UnixPath.toUnixPath(obj);
+        file.checkRead();
+        int mode = UnixNativeDispatcher.stat(file);
+        return ((mode & UnixConstants.S_IFMT) == UnixConstants.S_IFDIR);
+    }
+
+    @Override
+    public final boolean isRegularFile(Path obj) {
+        UnixPath file = UnixPath.toUnixPath(obj);
+        file.checkRead();
+        int mode = UnixNativeDispatcher.stat(file);
+        return ((mode & UnixConstants.S_IFMT) == UnixConstants.S_IFREG);
+    }
+
+    @Override
+    public final boolean exists(Path obj) {
+        UnixPath file = UnixPath.toUnixPath(obj);
+        file.checkRead();
+        return UnixNativeDispatcher.exists(file);
+    }
+
     /**
      * Returns a {@code FileTypeDetector} for this platform.
      */
--- a/jdk/src/java.base/unix/classes/sun/nio/fs/UnixNativeDispatcher.java	Wed Apr 13 15:05:50 2016 +0200
+++ b/jdk/src/java.base/unix/classes/sun/nio/fs/UnixNativeDispatcher.java	Wed Apr 13 14:29:25 2016 +0100
@@ -296,6 +296,23 @@
     private static native void stat0(long pathAddress, UnixFileAttributes attrs)
         throws UnixException;
 
+
+    /**
+     * stat(const char* path, struct stat* buf)
+     *
+     * @return st_mode (file type and mode) or 0 if an error occurs.
+     */
+    static int stat(UnixPath path) {
+        NativeBuffer buffer = copyToNativeBuffer(path);
+        try {
+            return stat1(buffer.address());
+        } finally {
+            buffer.release();
+        }
+    }
+    private static native int stat1(long pathAddress);
+
+
     /**
      * lstat(const char* path, struct stat* buf)
      */
@@ -459,6 +476,22 @@
     private static native void access0(long pathAddress, int amode) throws UnixException;
 
     /**
+     * access(constant char* path, F_OK)
+     *
+     * @return true if the file exists, false otherwise
+     */
+    static boolean exists(UnixPath path) {
+        NativeBuffer buffer = copyToNativeBuffer(path);
+        try {
+            return exists0(buffer.address());
+        } finally {
+            buffer.release();
+        }
+    }
+    private static native boolean exists0(long pathAddress);
+
+
+    /**
      * struct passwd *getpwuid(uid_t uid);
      *
      * @return  passwd->pw_name
--- a/jdk/src/java.base/unix/classes/sun/nio/fs/UnixUriUtils.java	Wed Apr 13 15:05:50 2016 +0200
+++ b/jdk/src/java.base/unix/classes/sun/nio/fs/UnixUriUtils.java	Wed Apr 13 14:29:25 2016 +0100
@@ -114,12 +114,9 @@
 
         // trailing slash if directory
         if (sb.charAt(sb.length()-1) != '/') {
-            try {
-                 if (UnixFileAttributes.get(up, true).isDirectory())
-                     sb.append('/');
-            } catch (UnixException x) {
-                // ignore
-            }
+            int mode = UnixNativeDispatcher.stat(up);
+            if ((mode & UnixConstants.S_IFMT) == UnixConstants.S_IFDIR)
+                sb.append('/');
         }
 
         try {
--- a/jdk/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c	Wed Apr 13 15:05:50 2016 +0200
+++ b/jdk/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c	Wed Apr 13 14:29:25 2016 +0100
@@ -483,6 +483,20 @@
     }
 }
 
+JNIEXPORT jint JNICALL
+Java_sun_nio_fs_UnixNativeDispatcher_stat1(JNIEnv* env, jclass this, jlong pathAddress) {
+    int err;
+    struct stat64 buf;
+    const char* path = (const char*)jlong_to_ptr(pathAddress);
+
+    RESTARTABLE(stat64(path, &buf), err);
+    if (err == -1) {
+        return 0;
+    } else {
+        return (jint)buf.st_mode;
+    }
+}
+
 JNIEXPORT void JNICALL
 Java_sun_nio_fs_UnixNativeDispatcher_lstat0(JNIEnv* env, jclass this,
     jlong pathAddress, jobject attrs)
@@ -897,6 +911,14 @@
     }
 }
 
+JNIEXPORT jboolean JNICALL
+Java_sun_nio_fs_UnixNativeDispatcher_exists0(JNIEnv* env, jclass this, jlong pathAddress) {
+    int err;
+    const char* path = (const char*)jlong_to_ptr(pathAddress);
+    RESTARTABLE(access(path, F_OK), err);
+    return (err == 0) ? JNI_TRUE : JNI_FALSE;
+}
+
 JNIEXPORT void JNICALL
 Java_sun_nio_fs_UnixNativeDispatcher_statvfs0(JNIEnv* env, jclass this,
     jlong pathAddress, jobject attrs)