Skip to content

Commit 587d778

Browse files
committed
svm: initialize FileSystemProviders at runtime (future-defaults)
1 parent b0c29d6 commit 587d778

File tree

5 files changed

+213
-10
lines changed

5 files changed

+213
-10
lines changed

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/FutureDefaultsOptions.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ public class FutureDefaultsOptions {
5454
private static final String NONE_NAME = "none";
5555
private static final String RUN_TIME_INITIALIZE_JDK_NAME = "run-time-initialized-jdk";
5656

57+
public static final String RUN_TIME_INITIALIZE_JDK_REASON = "Initialize JDK classes at run time (--" + OPTION_NAME + " includes " + RUN_TIME_INITIALIZE_JDK_NAME + ")";
58+
5759
private static final Set<String> ALL_VALUES = Set.of(RUN_TIME_INITIALIZE_JDK_NAME, ALL_NAME, NONE_NAME);
5860

5961
private static String futureDefaultsAllValues() {
@@ -66,7 +68,7 @@ private static String futureDefaultsAllValues() {
6668

6769
@APIOption(name = OPTION_NAME, defaultValue = DEFAULT_NAME) //
6870
@Option(help = "file:doc-files/FutureDefaultsHelp.txt", type = OptionType.User) //
69-
public static final HostedOptionKey<AccumulatingLocatableMultiOptionValue.Strings> FutureDefaults = new HostedOptionKey<>(
71+
static final HostedOptionKey<AccumulatingLocatableMultiOptionValue.Strings> FutureDefaults = new HostedOptionKey<>(
7072
AccumulatingLocatableMultiOptionValue.Strings.buildWithCommaDelimiter());
7173

7274
private static EconomicSet<String> futureDefaults;

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/FileSystemProviderSupport.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -142,7 +142,7 @@ public void afterRegistration(AfterRegistrationAccess access) {
142142
}
143143
}
144144

145-
@TargetClass(java.nio.file.spi.FileSystemProvider.class)
145+
@TargetClass(value = java.nio.file.spi.FileSystemProvider.class, onlyWith = JDKInitializedAtBuildTime.class)
146146
final class Target_java_nio_file_spi_FileSystemProvider {
147147
@Substitute
148148
public static List<FileSystemProvider> installedProviders() {
@@ -171,7 +171,7 @@ public static List<FileSystemProvider> installedProviders() {
171171
* c) Allow UnixFileSystem in the image heap and recompute state at run time on first acccess. This
172172
* approach is implemented here.
173173
*/
174-
@TargetClass(className = "sun.nio.fs.UnixFileSystem")
174+
@TargetClass(className = "sun.nio.fs.UnixFileSystem", onlyWith = JDKInitializedAtBuildTime.class)
175175
@Platforms({Platform.LINUX.class, Platform.DARWIN.class})
176176
final class Target_sun_nio_fs_UnixFileSystem {
177177

@@ -224,12 +224,12 @@ final class Target_sun_nio_fs_UnixFileSystem {
224224
native void originalConstructor(Target_sun_nio_fs_UnixFileSystemProvider p, String dir);
225225
}
226226

227-
@TargetClass(className = "sun.nio.fs.UnixFileSystemProvider")
227+
@TargetClass(className = "sun.nio.fs.UnixFileSystemProvider", onlyWith = JDKInitializedAtBuildTime.class)
228228
@Platforms({Platform.LINUX.class, Platform.DARWIN.class})
229229
final class Target_sun_nio_fs_UnixFileSystemProvider {
230230
}
231231

232-
@TargetClass(className = "sun.nio.fs.UnixPath")
232+
@TargetClass(className = "sun.nio.fs.UnixPath", onlyWith = JDKInitializedAtBuildTime.class)
233233
@Platforms({Platform.LINUX.class, Platform.DARWIN.class})
234234
final class Target_sun_nio_fs_UnixPath {
235235
}
@@ -403,7 +403,7 @@ private static synchronized void reinitialize(Target_sun_nio_fs_WindowsFileSyste
403403
}
404404
}
405405

406-
@TargetClass(className = "java.io.UnixFileSystem")
406+
@TargetClass(className = "java.io.UnixFileSystem", onlyWith = JDKInitializedAtBuildTime.class)
407407
@Platforms({Platform.LINUX.class, Platform.DARWIN.class})
408408
final class Target_java_io_UnixFileSystem {
409409

@@ -412,7 +412,7 @@ final class Target_java_io_UnixFileSystem {
412412
private String userDir;
413413
}
414414

415-
@TargetClass(className = "java.io.FileSystem")
415+
@TargetClass(className = "java.io.FileSystem", onlyWith = JDKInitializedAtBuildTime.class)
416416
final class Target_java_io_FileSystem {
417417

418418
@Alias
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
/*
2+
* Copyright (c) 2025, 2025, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
26+
package com.oracle.svm.core.jdk.runtimeinit;
27+
28+
import java.nio.file.FileSystem;
29+
import java.nio.file.spi.FileSystemProvider;
30+
import java.util.Objects;
31+
32+
import org.graalvm.nativeimage.Platform;
33+
import org.graalvm.nativeimage.Platforms;
34+
35+
import com.oracle.svm.core.SubstrateUtil;
36+
import com.oracle.svm.core.annotate.Alias;
37+
import com.oracle.svm.core.annotate.InjectAccessors;
38+
import com.oracle.svm.core.annotate.TargetClass;
39+
import com.oracle.svm.core.jdk.JDKInitializedAtRunTime;
40+
41+
/**
42+
* This file contains substitutions that are required for initializing {@link FileSystemProvider} at
43+
* image run time. Other related functionality (general and build time initialization) can be found
44+
* in {@link com.oracle.svm.core.jdk.FileSystemProviderSupport}.
45+
*
46+
* @see JDKInitializedAtRunTime
47+
* @see com.oracle.svm.core.jdk.FileSystemProviderSupport
48+
*/
49+
final class FileSystemProviderRuntimeInitSupport {
50+
}
51+
52+
// java.io
53+
54+
@TargetClass(className = "java.io.FileSystem", onlyWith = JDKInitializedAtRunTime.class)
55+
final class Target_java_io_FileSystem_RunTime {
56+
}
57+
58+
@TargetClass(className = "java.io.File", onlyWith = JDKInitializedAtRunTime.class)
59+
@SuppressWarnings("unused")
60+
final class Target_java_io_File_RunTime {
61+
@Alias //
62+
@InjectAccessors(DefaultFileSystemAccessor.class) //
63+
private static Target_java_io_FileSystem_RunTime FS;
64+
}
65+
66+
@TargetClass(className = "java.io.DefaultFileSystem", onlyWith = JDKInitializedAtRunTime.class)
67+
final class Target_java_io_DefaultFileSystem_RunTime {
68+
@Alias
69+
static native Target_java_io_FileSystem_RunTime getFileSystem();
70+
}
71+
72+
/**
73+
* Holds the default java.io file system. Initialized at run time via
74+
* {@code JDKInitializationFeature}.
75+
*/
76+
class DefaultFileSystemHolder {
77+
static final Target_java_io_FileSystem_RunTime FS;
78+
static {
79+
if (SubstrateUtil.HOSTED) {
80+
// unused - layered images might want to initialize during image build
81+
FS = null;
82+
} else {
83+
FS = Target_java_io_DefaultFileSystem_RunTime.getFileSystem();
84+
}
85+
}
86+
}
87+
88+
class DefaultFileSystemAccessor {
89+
@SuppressWarnings("unused")
90+
static Target_java_io_FileSystem_RunTime get() {
91+
return Objects.requireNonNull(DefaultFileSystemHolder.FS);
92+
}
93+
}
94+
95+
// sun.nio.fs
96+
97+
@TargetClass(className = "sun.nio.fs.DefaultFileSystemProvider", onlyWith = JDKInitializedAtRunTime.class)
98+
final class Target_sun_nio_fs_DefaultFileSystemProvider_RunTime {
99+
@Alias
100+
static native FileSystem theFileSystem();
101+
}
102+
103+
/**
104+
* Holds the default sun.nio.fs file system. Initialized at run time via
105+
* {@code JDKInitializationFeature}.
106+
*/
107+
class SunNioFsDefaultFileSystemHolder {
108+
static final FileSystem FS;
109+
110+
static {
111+
if (SubstrateUtil.HOSTED) {
112+
// unused - layered images might want to initialize during image build
113+
FS = null;
114+
} else {
115+
FS = Target_sun_nio_fs_DefaultFileSystemProvider_RunTime.theFileSystem();
116+
}
117+
}
118+
}
119+
120+
@TargetClass(className = "sun.nio.fs.UnixFileSystem", onlyWith = JDKInitializedAtRunTime.class)
121+
@Platforms({Platform.LINUX.class, Platform.DARWIN.class})
122+
final class Target_sun_nio_fs_UnixFileSystem_RunTime {
123+
}
124+
125+
@TargetClass(className = "sun.nio.fs.UnixPath", onlyWith = JDKInitializedAtRunTime.class)
126+
@Platforms({Platform.LINUX.class, Platform.DARWIN.class})
127+
final class Target_sun_nio_fs_UnixPath_RunTime {
128+
@Alias //
129+
@InjectAccessors(UnixFileSystemAccessor.class) //
130+
private Target_sun_nio_fs_UnixFileSystem_RunTime fs;
131+
}
132+
133+
@SuppressWarnings("unused")
134+
class UnixFileSystemAccessor {
135+
static Target_sun_nio_fs_UnixFileSystem_RunTime get(Target_sun_nio_fs_UnixPath_RunTime that) {
136+
return Objects.requireNonNull(SubstrateUtil.cast(SunNioFsDefaultFileSystemHolder.FS, Target_sun_nio_fs_UnixFileSystem_RunTime.class));
137+
}
138+
139+
static void set(Target_sun_nio_fs_UnixPath_RunTime that, Target_sun_nio_fs_UnixFileSystem_RunTime value) {
140+
/*
141+
* `value` should always be DefaultFileSystemProvider.INSTANCE.theFileSystem() but we cannot
142+
* check that here because it would introduce a class initialization cycle.
143+
*/
144+
}
145+
}
146+
147+
@TargetClass(className = "sun.nio.fs.WindowsFileSystem", onlyWith = JDKInitializedAtRunTime.class)
148+
@Platforms(Platform.WINDOWS.class)
149+
final class Target_sun_nio_fs_WindowsFileSystem_RunTime {
150+
}
151+
152+
@TargetClass(className = "sun.nio.fs.WindowsPath", onlyWith = JDKInitializedAtRunTime.class)
153+
@Platforms(Platform.WINDOWS.class)
154+
final class Target_sun_nio_fs_WindowsPath_RunTime {
155+
@Alias //
156+
@InjectAccessors(WindowsFileSystemAccessor.class) //
157+
private Target_sun_nio_fs_WindowsFileSystem_RunTime fs;
158+
}
159+
160+
@SuppressWarnings("unused")
161+
class WindowsFileSystemAccessor {
162+
static Target_sun_nio_fs_WindowsFileSystem_RunTime get(Target_sun_nio_fs_WindowsPath_RunTime that) {
163+
return Objects.requireNonNull(SubstrateUtil.cast(SunNioFsDefaultFileSystemHolder.FS, Target_sun_nio_fs_WindowsFileSystem_RunTime.class));
164+
}
165+
166+
static void set(Target_sun_nio_fs_WindowsPath_RunTime that, Target_sun_nio_fs_WindowsFileSystem_RunTime value) {
167+
/*
168+
* `value` should always be DefaultFileSystemProvider.INSTANCE.theFileSystem() but we cannot
169+
* check that here because it would introduce a class initialization cycle.
170+
*/
171+
}
172+
}

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JDKInitializationFeature.java

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2019, 2019, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -142,6 +142,34 @@ public void afterRegistration(AfterRegistrationAccess access) {
142142
rci.initializeAtBuildTime("java.awt.font.NumericShaper", "Required for sun.text.bidi.BidiBase.NumericShapings");
143143
rci.initializeAtBuildTime("java.awt.font.JavaAWTFontAccessImpl", "Required for sun.text.bidi.BidiBase.NumericShapings");
144144

145+
/* FileSystemProviders related */
146+
if (FutureDefaultsOptions.isJDKInitializedAtRunTime()) {
147+
rci.initializeAtRunTime("java.nio.file.spi", FutureDefaultsOptions.RUN_TIME_INITIALIZE_JDK_REASON);
148+
rci.initializeAtRunTime("sun.nio.fs", FutureDefaultsOptions.RUN_TIME_INITIALIZE_JDK_REASON);
149+
150+
rci.initializeAtRunTime("java.nio.file.FileSystems", FutureDefaultsOptions.RUN_TIME_INITIALIZE_JDK_REASON);
151+
rci.initializeAtRunTime("java.nio.file.FileSystems$DefaultFileSystemHolder", FutureDefaultsOptions.RUN_TIME_INITIALIZE_JDK_REASON);
152+
153+
rci.initializeAtRunTime("java.util.zip.ZipFile$Source", FutureDefaultsOptions.RUN_TIME_INITIALIZE_JDK_REASON);
154+
rci.initializeAtRunTime("java.util.zip.ZipFile$Source", FutureDefaultsOptions.RUN_TIME_INITIALIZE_JDK_REASON);
155+
156+
rci.initializeAtRunTime("java.io.FileSystem", FutureDefaultsOptions.RUN_TIME_INITIALIZE_JDK_REASON);
157+
rci.initializeAtRunTime("java.io.FileSystem$CurrentWorkingDirectoryHolder", FutureDefaultsOptions.RUN_TIME_INITIALIZE_JDK_REASON);
158+
rci.initializeAtRunTime("java.io.UnixFileSystem", FutureDefaultsOptions.RUN_TIME_INITIALIZE_JDK_REASON);
159+
rci.initializeAtRunTime("java.io.WindowsFileSystem", FutureDefaultsOptions.RUN_TIME_INITIALIZE_JDK_REASON);
160+
161+
rci.initializeAtBuildTime("java.io.File", FutureDefaultsOptions.RUN_TIME_INITIALIZE_JDK_REASON);
162+
rci.initializeAtBuildTime("sun.nio.fs.UnixPath", FutureDefaultsOptions.RUN_TIME_INITIALIZE_JDK_REASON);
163+
rci.initializeAtBuildTime("sun.nio.fs.WindowsPath", FutureDefaultsOptions.RUN_TIME_INITIALIZE_JDK_REASON);
164+
165+
// holder for the default file system
166+
rci.initializeAtRunTime("com.oracle.svm.core.jdk.runtimeinit.DefaultFileSystemHolder", FutureDefaultsOptions.RUN_TIME_INITIALIZE_JDK_REASON);
167+
rci.initializeAtRunTime("com.oracle.svm.core.jdk.runtimeinit.SunNioFsDefaultFileSystemHolder", FutureDefaultsOptions.RUN_TIME_INITIALIZE_JDK_REASON);
168+
169+
// JrtFS support
170+
rci.initializeAtBuildTime("jdk.internal.jrtfs.SystemImage", FutureDefaultsOptions.RUN_TIME_INITIALIZE_JDK_REASON);
171+
}
172+
145173
/* XML-related */
146174
if (FutureDefaultsOptions.isJDKInitializedAtRunTime()) {
147175
// GR-50683 should remove this part

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JDKRegistrations.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2020, 2020, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -65,6 +65,7 @@ public void duringSetup(DuringSetupAccess a) {
6565
* a `Random` object and the temporary directory in a static final field.
6666
*/
6767
initializeAtRunTime(a, "sun.nio.ch.UnixDomainSockets");
68+
initializeAtRunTime(a, "sun.nio.ch.UnixDomainSockets$UnnamedHolder");
6869

6970
initializeAtRunTime(a, "java.util.concurrent.ThreadLocalRandom$ThreadLocalRandomProxy");
7071

0 commit comments

Comments
 (0)