Skip to content

Commit 350a1ec

Browse files
committed
Check incompatible system properties
Many system properties are incompatible. Report warning for the usage of such properties at native image build and throw exception at run time.
1 parent 1e281f3 commit 350a1ec

File tree

3 files changed

+134
-2
lines changed

3 files changed

+134
-2
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package com.oracle.svm.core.jdk;
2+
3+
public class IncompatibleSystemPropertyException extends RuntimeException{
4+
public IncompatibleSystemPropertyException(String message){
5+
super(message);
6+
}
7+
}

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

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
import java.util.Properties;
3131
import java.util.function.Supplier;
3232

33+
import com.oracle.svm.core.option.RuntimeOptionKey;
34+
import org.graalvm.compiler.options.Option;
3335
import org.graalvm.nativeimage.ImageInfo;
3436
import org.graalvm.nativeimage.Platform;
3537
import org.graalvm.nativeimage.Platforms;
@@ -48,6 +50,11 @@
4850
*/
4951
public abstract class SystemPropertiesSupport {
5052

53+
public static class SystemPropertyFeatureOptions{
54+
@Option(help = "Report the usage of incompatible property as exception when it is not explicitly set)")//
55+
public static final RuntimeOptionKey<Boolean> ReportIncompatibleSystemPropertyError = new RuntimeOptionKey<>(false);
56+
}
57+
5158
/** System properties that are taken from the VM hosting the image generator. */
5259
private static final String[] HOSTED_PROPERTIES = {
5360
"java.version",
@@ -65,7 +72,36 @@ public abstract class SystemPropertiesSupport {
6572
"java.specification.version",
6673
"java.vm.specification.name",
6774
"java.vm.specification.vendor",
68-
"java.vm.specification.version"
75+
"java.vm.specification.version",
76+
"sun.arch.data.model"
77+
};
78+
79+
/**
80+
* System properties are unsupported by default.
81+
*/
82+
private static final String[] INCOMPATIBLE_PROPERTIES = {
83+
"awt.toolkit",
84+
"file.encoding.pkg",
85+
"java.awt.graphicsenv",
86+
"java.awt.printerjob",
87+
"java.home",
88+
"java.library.path",
89+
"java.runtime.name",
90+
"java.runtime.version",
91+
"java.vendor.url.bug",
92+
"java.vm.info",
93+
"sun.boot.class.path",
94+
"sun.boot.library.path",
95+
"sun.cpu.endian",
96+
"sun.cpu.isalist",
97+
"sun.io.unicode.encoding",
98+
"sun.java.command",
99+
"sun.java.launcher",
100+
"sun.management.compiler",
101+
"sun.os.patch.level",
102+
"user.country",
103+
"user.language",
104+
"user.timezone"
69105
};
70106

71107
/** System properties that are lazily computed at run time on first access. */
@@ -141,7 +177,20 @@ public Properties getProperties() {
141177

142178
protected String getProperty(String key) {
143179
initializeLazyValue(key);
144-
return properties.getProperty(key);
180+
String ret = properties.getProperty(key);
181+
if (ret == null && isIncompatible(key) && SystemPropertyFeatureOptions.ReportIncompatibleSystemPropertyError.getValue()) {
182+
throw new IncompatibleSystemPropertyException("Java system property " + key + " is incompatible in native image. Please explicitly assign the expected value via -D" + key + "=, or avoid using this property.");
183+
}
184+
return ret;
185+
}
186+
187+
public static boolean isIncompatible(String key) {
188+
for (int i = 0; i < INCOMPATIBLE_PROPERTIES.length; i++) {
189+
if (INCOMPATIBLE_PROPERTIES[i].equals(key)) {
190+
return true;
191+
}
192+
}
193+
return false;
145194
}
146195

147196
public void setProperties(Properties props) {
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/*
2+
* Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
3+
* Copyright (c) 2020 Alibaba Group Holding Limited. All Rights Reserved.
4+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5+
*
6+
* This code is free software; you can redistribute it and/or modify it
7+
* under the terms of the GNU General Public License version 2 only, as
8+
* published by the Free Software Foundation. Oracle designates this
9+
* particular file as subject to the "Classpath" exception as provided
10+
* by Oracle in the LICENSE file that accompanied this code.
11+
*
12+
* This code is distributed in the hope that it will be useful, but WITHOUT
13+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15+
* version 2 for more details (a copy is included in the LICENSE file that
16+
* accompanied this code).
17+
*
18+
* You should have received a copy of the GNU General Public License version
19+
* 2 along with this work; if not, write to the Free Software Foundation,
20+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21+
*
22+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
23+
* or visit www.oracle.com if you need additional information or have any
24+
* questions.
25+
*/
26+
package com.oracle.svm.hosted;
27+
28+
import com.oracle.svm.core.annotate.AutomaticFeature;
29+
import com.oracle.svm.core.graal.GraalFeature;
30+
import com.oracle.svm.core.jdk.SystemPropertiesSupport;
31+
import jdk.vm.ci.meta.ResolvedJavaMethod;
32+
import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
33+
import org.graalvm.compiler.nodes.ValueNode;
34+
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
35+
import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin;
36+
import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins;
37+
import org.graalvm.compiler.phases.util.Providers;
38+
39+
import java.util.Set;
40+
import java.util.concurrent.ConcurrentHashMap;
41+
42+
@AutomaticFeature
43+
public class SystemPropertyFeature implements GraalFeature {
44+
45+
private final Set<String> systemPropertyCalls = ConcurrentHashMap.newKeySet();
46+
47+
@Override
48+
public void afterImageWrite(AfterImageWriteAccess access) {
49+
if (!systemPropertyCalls.isEmpty()) {
50+
StringBuilder sb = new StringBuilder("\n\nNative image incompatible system properties are used in the program:\n");
51+
for (String s : systemPropertyCalls) {
52+
sb.append(" ").append(s).append("\n");
53+
}
54+
sb.append("The returned value of calling System.getProperty with these keys will be null in native image.\n");
55+
sb.append("Please make sure the expected property values are specified with -D when running the native image program or just avoid using them.\n\n");
56+
System.out.println(sb.toString());
57+
}
58+
}
59+
60+
@Override
61+
public void registerInvocationPlugins(Providers providers, SnippetReflectionProvider snippetReflection, InvocationPlugins invocationPlugins, boolean analysis, boolean hosted) {
62+
InvocationPlugins.Registration r = new InvocationPlugins.Registration(invocationPlugins, System.class);
63+
r.register1("getProperty", String.class, new InvocationPlugin() {
64+
@Override
65+
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode name) {
66+
if (name.isConstant()) {
67+
String propertyKey = snippetReflection.asObject(String.class, name.asJavaConstant());
68+
if (SystemPropertiesSupport.isIncompatible(propertyKey)) {
69+
systemPropertyCalls.add("Incompatible property:" + propertyKey + " is used at " + b.getCode().asStackTraceElement(b.bci()));
70+
}
71+
}
72+
return false;
73+
}
74+
});
75+
}
76+
}

0 commit comments

Comments
 (0)