From 33a3b1cdf07e752c4f5ae425ff5b3b0bf80f5477 Mon Sep 17 00:00:00 2001 From: Alan Bateman Date: Wed, 13 Apr 2016 14:29:25 +0100 Subject: [PATCH] 8154077: (fs) Reduce number of file system classes loaded during startup Reviewed-by: bpb, chegar --- jdk/make/mapfiles/libnio/mapfile-linux | 2 + jdk/make/mapfiles/libnio/mapfile-macosx | 2 + jdk/make/mapfiles/libnio/mapfile-solaris | 2 + .../share/classes/java/nio/file/Files.java | 20 ++++++++ .../nio/fs/AbstractFileSystemProvider.java | 51 ++++++++++++++++++- .../sun/nio/fs/UnixFileSystemProvider.java | 23 +++++++++ .../sun/nio/fs/UnixNativeDispatcher.java | 33 ++++++++++++ .../unix/classes/sun/nio/fs/UnixUriUtils.java | 9 ++-- .../native/libnio/fs/UnixNativeDispatcher.c | 22 ++++++++ 9 files changed, 156 insertions(+), 8 deletions(-) diff --git a/jdk/make/mapfiles/libnio/mapfile-linux b/jdk/make/mapfiles/libnio/mapfile-linux index e4563b10c12..f2676187ed5 100644 --- a/jdk/make/mapfiles/libnio/mapfile-linux +++ b/jdk/make/mapfiles/libnio/mapfile-linux @@ -161,7 +161,9 @@ SUNWprivate_1.1 { 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; diff --git a/jdk/make/mapfiles/libnio/mapfile-macosx b/jdk/make/mapfiles/libnio/mapfile-macosx index daee0371e3c..a3f6d5d9c1c 100644 --- a/jdk/make/mapfiles/libnio/mapfile-macosx +++ b/jdk/make/mapfiles/libnio/mapfile-macosx @@ -138,7 +138,9 @@ SUNWprivate_1.1 { 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; diff --git a/jdk/make/mapfiles/libnio/mapfile-solaris b/jdk/make/mapfiles/libnio/mapfile-solaris index a1e0d99b0e6..a38701ab3b5 100644 --- a/jdk/make/mapfiles/libnio/mapfile-solaris +++ b/jdk/make/mapfiles/libnio/mapfile-solaris @@ -138,7 +138,9 @@ SUNWprivate_1.1 { 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; diff --git a/jdk/src/java.base/share/classes/java/nio/file/Files.java b/jdk/src/java.base/share/classes/java/nio/file/Files.java index 982846e6e25..e1ab41b7759 100644 --- a/jdk/src/java.base/share/classes/java/nio/file/Files.java +++ b/jdk/src/java.base/share/classes/java/nio/file/Files.java @@ -77,6 +77,8 @@ import java.util.function.BiPredicate; 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 @@ public final class Files { * 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 @@ public final class Files { * 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 @@ public final class Files { * @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); diff --git a/jdk/src/java.base/share/classes/sun/nio/fs/AbstractFileSystemProvider.java b/jdk/src/java.base/share/classes/sun/nio/fs/AbstractFileSystemProvider.java index 9e1dc6133ac..0e325414f5d 100644 --- a/jdk/src/java.base/share/classes/sun/nio/fs/AbstractFileSystemProvider.java +++ b/jdk/src/java.base/share/classes/sun/nio/fs/AbstractFileSystemProvider.java @@ -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 @@ import java.util.Map; * Base implementation class of FileSystemProvider */ -abstract class AbstractFileSystemProvider extends FileSystemProvider { +public abstract class AbstractFileSystemProvider extends FileSystemProvider { protected AbstractFileSystemProvider() { } /** @@ -107,4 +109,49 @@ abstract class AbstractFileSystemProvider extends FileSystemProvider { 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; + } + } } diff --git a/jdk/src/java.base/unix/classes/sun/nio/fs/UnixFileSystemProvider.java b/jdk/src/java.base/unix/classes/sun/nio/fs/UnixFileSystemProvider.java index f161bd3e0bf..b738cc3c5d2 100644 --- a/jdk/src/java.base/unix/classes/sun/nio/fs/UnixFileSystemProvider.java +++ b/jdk/src/java.base/unix/classes/sun/nio/fs/UnixFileSystemProvider.java @@ -499,6 +499,29 @@ public abstract class UnixFileSystemProvider } } + @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. */ diff --git a/jdk/src/java.base/unix/classes/sun/nio/fs/UnixNativeDispatcher.java b/jdk/src/java.base/unix/classes/sun/nio/fs/UnixNativeDispatcher.java index c64374125cb..e6a62faf966 100644 --- a/jdk/src/java.base/unix/classes/sun/nio/fs/UnixNativeDispatcher.java +++ b/jdk/src/java.base/unix/classes/sun/nio/fs/UnixNativeDispatcher.java @@ -296,6 +296,23 @@ class UnixNativeDispatcher { 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) */ @@ -458,6 +475,22 @@ class UnixNativeDispatcher { } 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); * diff --git a/jdk/src/java.base/unix/classes/sun/nio/fs/UnixUriUtils.java b/jdk/src/java.base/unix/classes/sun/nio/fs/UnixUriUtils.java index a0df3e3102e..45fd404e8c0 100644 --- a/jdk/src/java.base/unix/classes/sun/nio/fs/UnixUriUtils.java +++ b/jdk/src/java.base/unix/classes/sun/nio/fs/UnixUriUtils.java @@ -114,12 +114,9 @@ class UnixUriUtils { // 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 { diff --git a/jdk/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c b/jdk/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c index 7e6e5286473..fe203cdf2dc 100644 --- a/jdk/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c +++ b/jdk/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c @@ -483,6 +483,20 @@ Java_sun_nio_fs_UnixNativeDispatcher_stat0(JNIEnv* env, jclass this, } } +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 @@ Java_sun_nio_fs_UnixNativeDispatcher_access0(JNIEnv* env, jclass this, } } +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)