28
28
import java .util .HashMap ;
29
29
import java .util .Map ;
30
30
import java .util .Properties ;
31
+ import java .util .concurrent .ConcurrentHashMap ;
32
+ import java .util .function .BooleanSupplier ;
31
33
import java .util .function .Supplier ;
32
34
35
+ import com .oracle .svm .core .option .RuntimeOptionKey ;
36
+ import org .graalvm .compiler .options .Option ;
33
37
import org .graalvm .nativeimage .ImageInfo ;
34
38
import org .graalvm .nativeimage .Platform ;
35
39
import org .graalvm .nativeimage .Platforms ;
41
45
* This class maintains the system properties at run time.
42
46
*
43
47
* Some of the standard system properties can just be taken from the image generator:
44
- * {@link #HOSTED_PROPERTIES}. Other important system properties need to be computed at run time.
48
+ * Other important system properties need to be computed at run time.
45
49
* However, we want to do the computation lazily to reduce the startup cost. For example, getting
46
50
* the current working directory is quite expensive. We initialize such a property either when it is
47
51
* explicitly accessed, or when all properties are accessed.
48
52
*/
49
53
public abstract class SystemPropertiesSupport {
50
54
51
- /** System properties that are taken from the VM hosting the image generator. */
52
- private static final String [] HOSTED_PROPERTIES = {
53
- "java.version" ,
54
- ImageInfo .PROPERTY_IMAGE_KIND_KEY ,
55
- /*
56
- * We do not support cross-compilation for now. Separator might also be cached
57
- * in other classes, so changing them would be tricky.
58
- */
59
- "line.separator" , "path.separator" , "file.separator" ,
60
- /* For our convenience for now. */
61
- "file.encoding" , "sun.jnu.encoding" ,
62
- "java.class.version" ,
63
- "java.specification.name" ,
64
- "java.specification.vendor" ,
65
- "java.specification.version" ,
66
- "java.vm.specification.name" ,
67
- "java.vm.specification.vendor" ,
68
- "java.vm.specification.version"
69
- };
55
+ public static class SystemPropertyFeatureOptions {
56
+ @ Option (help = "Report the usage of undefined property as exception when it is not explicitly set)" )//
57
+ public static final RuntimeOptionKey <Boolean > ReportUndefinedSystemPropertyError = new RuntimeOptionKey <>(false );
58
+ }
59
+
60
+ private enum InitKind {AsHosted , Runtime , BuildTime , Undefined }
61
+
62
+ private static class PropertyInfo {
63
+ private String name ;
64
+ private BooleanSupplier onlyWith ;
65
+ private InitKind initKind ;
66
+ private Supplier <String > initValue ;
67
+
68
+ public PropertyInfo (String name , BooleanSupplier onlyWith , InitKind InitKind , Supplier <String > initValue ) {
69
+ if (name == null ) {
70
+ throw new NullPointerException ("Property name should never be null!" );
71
+ }
72
+ this .name = name ;
73
+ this .onlyWith = onlyWith ;
74
+ this .initKind = InitKind ;
75
+ this .initValue = initValue ;
76
+ }
77
+
78
+ }
79
+
80
+ private static final Map <String , PropertyInfo > SYSTEM_PROPERTIES = new ConcurrentHashMap <>();
81
+
82
+ private static final JDK8OrEarlier jdk8OrEarlier = new JDK8OrEarlier ();
83
+ private static final JDK11OrLater jdk11OrLater = new JDK11OrLater ();
84
+ private static final BooleanSupplier always = ()-> true ;
85
+ private static final Supplier <String > STRING_SUPPLIER_SUPPLIER = () -> "" ;
86
+
87
+ static {
88
+ //Set properties same as hosted
89
+ addAsHostedSystemProperty ("file.encoding" , always );
90
+ // https://github.com/openjdk/jdk/commit/d4941f14af150fb81db7cff5394192637be701dd
91
+ addAsHostedSystemProperty ("file.encoding.pkg" , jdk8OrEarlier );
92
+ addAsHostedSystemProperty ("file.separator" , always );
93
+ addAsHostedSystemProperty ("java.class.version" , always );
94
+ addAsHostedSystemProperty ("java.runtime.version" , always );
95
+ addAsHostedSystemProperty ("java.specification.name" , always );
96
+ addAsHostedSystemProperty ("java.specification.vendor" , always );
97
+ addAsHostedSystemProperty ("java.specification.version" , always );
98
+ addAsHostedSystemProperty ("java.version" , always );
99
+ // https://openjdk.java.net/jeps/322
100
+ addAsHostedSystemProperty ("java.version.date" , jdk11OrLater );
101
+ addAsHostedSystemProperty ("java.vendor.version" , jdk11OrLater );
102
+ addAsHostedSystemProperty ("java.vm.specification.name" , always );
103
+ addAsHostedSystemProperty ("java.vm.specification.vendor" , always );
104
+ addAsHostedSystemProperty ("java.vm.specification.version" , always );
105
+ addAsHostedSystemProperty ("line.separator" , always );
106
+ addAsHostedSystemProperty ("path.separator" , always );
107
+ addAsHostedSystemProperty ("sun.cpu.endian" , always );
108
+ addAsHostedSystemProperty ("sun.cpu.isalist" , always );
109
+ addAsHostedSystemProperty ("sun.jnu.encoding" , always );
110
+ addAsHostedSystemProperty ("sun.io.unicode.encoding" , always );
111
+ addAsHostedSystemProperty (ImageInfo .PROPERTY_IMAGE_KIND_KEY , always );
112
+
113
+ //Undefined properties
114
+ addUndefinedSystemProperty ("awt.toolkit" , always );
115
+ addUndefinedSystemProperty ("java.awt.graphicsenv" , always );
116
+ addUndefinedSystemProperty ("java.awt.printerjob" , always );
117
+ addUndefinedSystemProperty ("java.home" , always );
118
+ addUndefinedSystemProperty ("sun.java.command" , always );
119
+ addUndefinedSystemProperty ("sun.java.launcher" , always );
120
+ addUndefinedSystemProperty ("sun.os.patch.level" , always );
121
+ addUndefinedSystemProperty ("user.country" , always );
122
+ addUndefinedSystemProperty ("user.language" , always );
123
+ addUndefinedSystemProperty ("user.timezone" , always );
124
+ // http://hg.openjdk.java.net/jdk9/jdk9/hotspot/rev/3b241fb72b89
125
+ addUndefinedSystemProperty ("java.vm.compressedOopsMode" , jdk11OrLater );
126
+ // http://hg.openjdk.java.net/jdk9/jdk9/hotspot/rev/39c579b50006
127
+ addUndefinedSystemProperty ("jdk.debug" , jdk11OrLater );
128
+
129
+ // Build time initialized properties
130
+ addSystemProperty ("java.class.path" , always , InitKind .BuildTime , STRING_SUPPLIER_SUPPLIER );
131
+ // http://hg.openjdk.java.net/jdk9/jdk9/jdk/rev/e336cbd8b15e
132
+ addSystemProperty ("java.endorsed.dirs" , jdk8OrEarlier , InitKind .BuildTime , STRING_SUPPLIER_SUPPLIER );
133
+ addSystemProperty ("java.ext.dirs" , jdk8OrEarlier , InitKind .BuildTime , STRING_SUPPLIER_SUPPLIER );
134
+ addSystemProperty ("java.runtime.name" , always , InitKind .BuildTime , ()->"Substrate VM Runtime Environment" );
135
+ addSystemProperty ("java.vendor" , always , InitKind .BuildTime , ()->"Oracle Corporation" );
136
+ addSystemProperty ("java.vendor.url.bug" , always , InitKind .BuildTime , ()->"https://github.com/oracle/graal/issues" );
137
+ addSystemProperty ("java.vm.info" , always , InitKind .BuildTime , ()->"static mode" );
138
+ addSystemProperty ("java.vm.name" , always , InitKind .BuildTime , () ->"Substrate VM" );
139
+ addSystemProperty ("java.vm.vendor" , always , InitKind .BuildTime , ()->"Oracle Corporation" );
140
+ addSystemProperty ("java.vendor.url" , always , InitKind .BuildTime , ()->"https://www.graalvm.org/" );
141
+ String targetArch = System .getProperty ("svm.targetArch" );
142
+ addSystemProperty ("os.arch" , always , InitKind .BuildTime , ()->targetArch != null ? targetArch : System .getProperty ("os.arch" ));
143
+ String targetName = System .getProperty ("svm.targetName" );
144
+ addSystemProperty ("os.name" , always , InitKind .BuildTime , ()->targetName != null ? targetName : System .getProperty ("os.name" ));
145
+ addSystemProperty ("sun.arch.data.model" , always , InitKind .BuildTime , ()->Integer .toString (ConfigurationValues .getTarget ().wordJavaKind .getBitCount ()));
146
+ // http://openjdk.java.net/jeps/261 http://hg.openjdk.java.net/jdk9/jdk9/hotspot/rev/c558850fac57
147
+ addSystemProperty ("sun.boot.class.path" , jdk8OrEarlier , InitKind .BuildTime , STRING_SUPPLIER_SUPPLIER );
148
+ addSystemProperty ("sun.management.compiler" , always , InitKind .BuildTime ,()-> "GraalVM Compiler" );
149
+ addSystemProperty (ImageInfo .PROPERTY_IMAGE_CODE_KEY , always , InitKind .BuildTime , ()->ImageInfo .PROPERTY_IMAGE_CODE_VALUE_RUNTIME );
150
+ }
70
151
71
152
/** System properties that are lazily computed at run time on first access. */
72
153
private final Map <String , Supplier <String >> lazyRuntimeValues ;
@@ -83,37 +164,43 @@ protected SystemPropertiesSupport() {
83
164
savedProperties = new HashMap <>();
84
165
readOnlySavedProperties = Collections .unmodifiableMap (savedProperties );
85
166
86
- for (String key : HOSTED_PROPERTIES ) {
87
- String value = System .getProperty (key );
88
- properties .put (key , value );
89
- savedProperties .put (key , value );
90
- }
91
-
92
- initializeProperty ("java.vm.name" , "Substrate VM" );
93
- initializeProperty ("java.vm.vendor" , "Oracle Corporation" );
94
- initializeProperty ("java.vendor" , "Oracle Corporation" );
95
- initializeProperty ("java.vendor.url" , "https://www.graalvm.org/" );
167
+ // Runtime initialized properties
168
+ addSystemProperty ("user.name" , always , InitKind .Runtime , this ::userName );
169
+ addSystemProperty ("user.home" , always , InitKind .Runtime , this ::userHome );
170
+ addSystemProperty ("user.dir" , always , InitKind .Runtime , this ::userDir );
171
+ addSystemProperty ("java.io.tmpdir" , always , InitKind .Runtime , this ::tmpdirValue );
172
+ addSystemProperty ("os.version" , always , InitKind .Runtime , this ::osVersionValue );
173
+ addSystemProperty ("java.vm.version" , always , InitKind .Runtime , VM ::getVersion );
96
174
97
- initializeProperty ("java.class.path" , "" );
98
- initializeProperty ("java.endorsed.dirs" , "" );
99
- initializeProperty ("java.ext.dirs" , "" );
100
- initializeProperty ("java.library.path" , "" );
101
- initializeProperty ("sun.arch.data.model" , Integer .toString (ConfigurationValues .getTarget ().wordJavaKind .getBitCount ()));
175
+ lazyRuntimeValues = new HashMap <>();
176
+ SYSTEM_PROPERTIES .forEach ((key , propertyInfo ) -> {
177
+ if (propertyInfo .onlyWith .getAsBoolean ()) {
178
+ switch (propertyInfo .initKind ){
179
+ case AsHosted :
180
+ initializeProperty (key , System .getProperty (key ));
181
+ break ;
182
+ case BuildTime :
183
+ initializeProperty (key , propertyInfo .initValue .get ());
184
+ break ;
185
+ case Undefined :
186
+ break ;
187
+ case Runtime :
188
+ lazyRuntimeValues .put (key , propertyInfo .initValue );
189
+ }
190
+ }
191
+ });
192
+ }
102
193
103
- String targetName = System .getProperty ("svm.targetName" );
104
- String targetArch = System .getProperty ("svm.targetArch" );
105
- initializeProperty ("os.name" , targetName != null ? targetName : System .getProperty ("os.name" ));
106
- initializeProperty ("os.arch" , targetArch != null ? targetArch : System .getProperty ("os.arch" ));
194
+ private static void addSystemProperty (String name , BooleanSupplier onlyWith , InitKind InitKind , Supplier <String > initValue ){
195
+ SYSTEM_PROPERTIES .put (name ,new PropertyInfo (name , onlyWith , InitKind , initValue ));
196
+ }
107
197
108
- initializeProperty (ImageInfo .PROPERTY_IMAGE_CODE_KEY , ImageInfo .PROPERTY_IMAGE_CODE_VALUE_RUNTIME );
198
+ private static void addUndefinedSystemProperty (String name , BooleanSupplier onlyWith ) {
199
+ SYSTEM_PROPERTIES .put (name ,new PropertyInfo (name , onlyWith , InitKind .Undefined , null ));
200
+ }
109
201
110
- lazyRuntimeValues = new HashMap <>();
111
- lazyRuntimeValues .put ("user.name" , this ::userName );
112
- lazyRuntimeValues .put ("user.home" , this ::userHome );
113
- lazyRuntimeValues .put ("user.dir" , this ::userDir );
114
- lazyRuntimeValues .put ("java.io.tmpdir" , this ::tmpdirValue );
115
- lazyRuntimeValues .put ("os.version" , this ::osVersionValue );
116
- lazyRuntimeValues .put ("java.vm.version" , VM ::getVersion );
202
+ private static void addAsHostedSystemProperty (String name , BooleanSupplier onlyWith ){
203
+ SYSTEM_PROPERTIES .put (name ,new PropertyInfo (name , onlyWith , InitKind .AsHosted , null ));
117
204
}
118
205
119
206
private void ensureFullyInitialized () {
@@ -141,7 +228,16 @@ public Properties getProperties() {
141
228
142
229
protected String getProperty (String key ) {
143
230
initializeLazyValue (key );
144
- return properties .getProperty (key );
231
+ String ret = properties .getProperty (key );
232
+ if (ret == null && isUndefined (key ) && SystemPropertyFeatureOptions .ReportUndefinedSystemPropertyError .getValue ()) {
233
+ throw new UndefinedSystemPropertyException ("Java system property " + key + " is undefined in native image. Please explicitly assign the expected value via -D" + key + "=, or avoid using this property." );
234
+ }
235
+ return ret ;
236
+ }
237
+
238
+ public static boolean isUndefined (String key ) {
239
+ PropertyInfo propertyInfo = SYSTEM_PROPERTIES .get (key );
240
+ return propertyInfo != null && propertyInfo .initKind == InitKind .Undefined ;
145
241
}
146
242
147
243
public void setProperties (Properties props ) {
0 commit comments