Skip to content

Commit ed5f5f8

Browse files
committed
[GR-12275] Make native-image & native-image-maven-plugin work with Java11+.
PullRequest: graal/2440
2 parents 2e80cb0 + f688c00 commit ed5f5f8

File tree

9 files changed

+346
-192
lines changed

9 files changed

+346
-192
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
*.bgv
55
*.cfg
66
*.class
7+
*.config
78
*.csv
89
*.dot
910
*.hprof

substratevm/PROPERTIES.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Using System Properties in Substrate VM images
2+
3+
Lets assume you have the following Java Program
4+
```java
5+
public class App {
6+
public static void main(String[] args) {
7+
System.getProperties().list(System.out);
8+
}
9+
}
10+
```
11+
If you compile that with e.g. `native-image -Dfoo=bar App` the system property `foo` will be available at *image build-time*. I.e. whenever you are in [code that is part of your application but executed at *image build-time*](http://www.graalvm.org/sdk/javadoc/org/graalvm/nativeimage/ImageInfo.html#inImageBuildtimeCode--) (usually static field initializations & static initializers). Thus if you execute the image above it will **not** contain `foo` in the list of properties.
12+
13+
If, on the other hand, you now execute the image with: `app -Dfoo=bar` it will show `foo` in the list of properties because you specified it for *image run-time*.
14+
15+
In other words:
16+
* Passing `-D<key>=<value>` to `native-image` affects properties seen at *image build-time*.
17+
* Passing `-D<key>=<value>` to an image execution affects properties seen at *image run-time*.

substratevm/mx.substratevm/mx_substratevm.py

Lines changed: 124 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -56,74 +56,92 @@
5656
from mx_substratevm_benchmark import run_js, host_vm_tuple, output_processors, rule_snippets # pylint: disable=unused-import
5757
from mx_unittest import _run_tests, _VMLauncher
5858

59-
GRAAL_COMPILER_FLAGS = [
59+
GRAAL_COMPILER_FLAGS_BASE = [
60+
'-XX:+UnlockExperimentalVMOptions',
61+
'-XX:+EnableJVMCI',
6062
'-XX:-UseJVMCICompiler', # GR-8656: Do not run with Graal as JIT compiler until libgraal is available.
6163
'-Dtruffle.TrustAllTruffleRuntimeProviders=true', # GR-7046
6264
]
6365

64-
if mx.get_jdk(tag='default').javaCompliance <= mx.JavaCompliance('1.8'):
65-
GRAAL_COMPILER_FLAGS += ['-XX:-UseJVMCIClassLoader']
66+
GRAAL_COMPILER_FLAGS_MAP = dict()
67+
GRAAL_COMPILER_FLAGS_MAP['1.8'] = ['-d64', '-noverify', '-XX:-UseJVMCIClassLoader']
68+
GRAAL_COMPILER_FLAGS_MAP['11'] = []
69+
# Disable the check for JDK-8 graal version.
70+
GRAAL_COMPILER_FLAGS_MAP['11'] += ['-Dsubstratevm.IgnoreGraalVersionCheck=true']
71+
# GR-11937: Use bytecodes instead of invoke-dynamic for string concatenation.
72+
GRAAL_COMPILER_FLAGS_MAP['11'] += ['-Djava.lang.invoke.stringConcat=BC_SB']
73+
74+
75+
# Turn a list of package names into a list of `--add-exports` command line arguments.
76+
def add_exports_from_packages(packageNameList):
77+
# Return one command line argument (pair) for one package name.
78+
def add_exports_to_all_unnamed(packageName):
79+
return ['--add-exports', packageName + '=ALL-UNNAMED']
80+
81+
return itertools.chain.from_iterable(add_exports_to_all_unnamed(package) for package in packageNameList)
82+
83+
84+
# Turn a list of package names into a list of `--add-opens` command line arguments.
85+
def add_opens_from_packages(packageNameList):
86+
# Return one command line argument (pair) for one package name.
87+
def add_opens_to_all_unnamed(packageName):
88+
return ['--add-opens', packageName + '=ALL-UNNAMED']
89+
90+
return itertools.chain.from_iterable(add_opens_to_all_unnamed(package) for package in packageNameList)
91+
92+
93+
# JVMCI access
94+
graal_compiler_export_packages = [
95+
'jdk.internal.vm.ci/jdk.vm.ci.runtime',
96+
'jdk.internal.vm.ci/jdk.vm.ci.code',
97+
'jdk.internal.vm.ci/jdk.vm.ci.amd64',
98+
'jdk.internal.vm.ci/jdk.vm.ci.meta',
99+
'jdk.internal.vm.ci/jdk.vm.ci.hotspot',
100+
'jdk.internal.vm.ci/jdk.vm.ci.common']
101+
GRAAL_COMPILER_FLAGS_MAP['11'].extend(add_exports_from_packages(graal_compiler_export_packages))
102+
103+
# Packages to open to allow reflective access at runtime.
104+
jdk_opens_packages = [
105+
# Reflective access
106+
'jdk.unsupported/sun.reflect',
107+
# Reflective access to jdk.internal.module.Modules, using which I can export and open other modules.
108+
'java.base/jdk.internal.module'
109+
]
110+
GRAAL_COMPILER_FLAGS_MAP['11'].extend(add_opens_from_packages(jdk_opens_packages))
111+
112+
# These packages should be opened at runtime calls to Modules.addOpens, if they are still needed.
113+
java_base_opens_packages = [
114+
# Reflective access to jdk.internal.ref.CleanerImpl$PhantomCleanableRef.
115+
'java.base/jdk.internal.ref',
116+
# Reflective access to private fields of java.lang.Class.
117+
'java.base/java.lang',
118+
# Reflective access to java.lang.invoke.VarHandle*.
119+
'java.base/java.lang.invoke',
120+
# Reflective access to java.lang.Reference.referent.
121+
'java.base/java.lang.ref',
122+
# Reflective access to java.net.URL.getURLStreamHandler.
123+
'java.base/java.net',
124+
# Reflective access to java.nio.MappedByteBuffer.fd.
125+
'java.base/java.nio',
126+
# Reflective access to java.util.Bits.words.
127+
'java.base/java.util']
128+
GRAAL_COMPILER_FLAGS_MAP['11'].extend(add_opens_from_packages(java_base_opens_packages))
129+
130+
# Reflective access to org.graalvm.nativeimage.impl.ImageSingletonsSupport.
131+
graal_sdk_opens_packages = [
132+
'org.graalvm.sdk/org.graalvm.nativeimage.impl']
133+
GRAAL_COMPILER_FLAGS_MAP['11'].extend(add_opens_from_packages(graal_sdk_opens_packages))
134+
135+
def svm_java_compliance():
136+
return mx.get_jdk(tag='default').javaCompliance
137+
138+
def svm_java80():
139+
return svm_java_compliance() <= mx.JavaCompliance('1.8')
140+
141+
if svm_java80():
142+
GRAAL_COMPILER_FLAGS = GRAAL_COMPILER_FLAGS_BASE + GRAAL_COMPILER_FLAGS_MAP['1.8']
66143
else:
67-
# Disable the check for JDK-8 graal version.
68-
GRAAL_COMPILER_FLAGS += ['-Dsubstratevm.IgnoreGraalVersionCheck=true']
69-
# GR-11937: Use bytecodes instead of invoke-dynamic for string concatenation.
70-
GRAAL_COMPILER_FLAGS += ['-Djava.lang.invoke.stringConcat=BC_SB']
71-
72-
# Turn a list of package names into a list of `--add-exports` command line arguments.
73-
def add_exports_from_packages(packageNameList):
74-
# Return one command line argument (pair) for one package name.
75-
def add_exports_to_all_unnamed(packageName):
76-
return ['--add-exports', packageName + '=ALL-UNNAMED']
77-
return itertools.chain.from_iterable(add_exports_to_all_unnamed(package) for package in packageNameList)
78-
79-
# Turn a list of package names into a list of `--add-opens` command line arguments.
80-
def add_opens_from_packages(packageNameList):
81-
# Return one command line argument (pair) for one package name.
82-
def add_opens_to_all_unnamed(packageName):
83-
return ['--add-opens', packageName + '=ALL-UNNAMED']
84-
return itertools.chain.from_iterable(add_opens_to_all_unnamed(package) for package in packageNameList)
85-
86-
# JVMCI access
87-
graal_compiler_export_packages = [
88-
'jdk.internal.vm.ci/jdk.vm.ci.runtime',
89-
'jdk.internal.vm.ci/jdk.vm.ci.code',
90-
'jdk.internal.vm.ci/jdk.vm.ci.amd64',
91-
'jdk.internal.vm.ci/jdk.vm.ci.meta',
92-
'jdk.internal.vm.ci/jdk.vm.ci.hotspot',
93-
'jdk.internal.vm.ci/jdk.vm.ci.common']
94-
GRAAL_COMPILER_FLAGS.extend(add_exports_from_packages(graal_compiler_export_packages))
95-
96-
# Packages to open to allow reflective access at runtime.
97-
jdk_opens_packages = [
98-
# Reflective access
99-
'jdk.unsupported/sun.reflect',
100-
# Reflective access to jdk.internal.module.Modules, using which I can export and open other modules.
101-
'java.base/jdk.internal.module'
102-
]
103-
GRAAL_COMPILER_FLAGS.extend(add_opens_from_packages(jdk_opens_packages))
104-
105-
# These packages should be opened at runtime calls to Modules.addOpens, if they are still needed.
106-
java_base_opens_packages = [
107-
# Reflective access to jdk.internal.ref.CleanerImpl$PhantomCleanableRef.
108-
'java.base/jdk.internal.ref',
109-
# Reflective access to private fields of java.lang.Class.
110-
'java.base/java.lang',
111-
# Reflective access to java.lang.invoke.VarHandle*.
112-
'java.base/java.lang.invoke',
113-
# Reflective access to java.lang.Reference.referent.
114-
'java.base/java.lang.ref',
115-
# Reflective access to java.net.URL.getURLStreamHandler.
116-
'java.base/java.net',
117-
# Reflective access to java.nio.MappedByteBuffer.fd.
118-
'java.base/java.nio',
119-
# Reflective access to java.util.Bits.words.
120-
'java.base/java.util']
121-
GRAAL_COMPILER_FLAGS.extend(add_opens_from_packages(java_base_opens_packages))
122-
123-
# Reflective access to org.graalvm.nativeimage.impl.ImageSingletonsSupport.
124-
graal_sdk_opens_packages = [
125-
'org.graalvm.sdk/org.graalvm.nativeimage.impl']
126-
GRAAL_COMPILER_FLAGS.extend(add_opens_from_packages(graal_sdk_opens_packages))
144+
GRAAL_COMPILER_FLAGS = GRAAL_COMPILER_FLAGS_BASE + GRAAL_COMPILER_FLAGS_MAP['11']
127145

128146
IMAGE_ASSERTION_FLAGS = ['-H:+VerifyGraalGraphs', '-H:+VerifyGraalGraphEdges', '-H:+VerifyPhases']
129147
suite = mx.suite('substratevm')
@@ -167,7 +185,7 @@ def svmbuild_dir(suite=None):
167185
def suite_native_image_root(suite=None):
168186
if not suite:
169187
suite = svm_suite()
170-
root_dir = join(svmbuild_dir(suite), 'native-image-root')
188+
root_dir = join(svmbuild_dir(suite), 'native-image-root-' + str(svm_java_compliance()))
171189
rev_file_name = join(root_dir, 'rev')
172190
rev_value = suite.vc.parent(suite.vc_dir)
173191
def write_rev_file():
@@ -344,17 +362,24 @@ def native_image_layout_dists(subdir, dist_names):
344362
def native_image_extract_dists(subdir, dist_names):
345363
native_image_extract(names_to_dists(dist_names), subdir, native_image_root)
346364

347-
# Create native-image layout for sdk parts
348-
native_image_layout_dists(join('lib', 'boot'), ['sdk:GRAAL_SDK'])
349365
native_image_layout_dists(join('lib', 'graalvm'), ['substratevm:SVM_DRIVER', 'sdk:LAUNCHER_COMMON'])
350366

367+
# Create native-image layout for sdk parts
368+
graal_sdk_dists = ['sdk:GRAAL_SDK']
369+
if svm_java80():
370+
native_image_layout_dists(join('lib', 'boot'), graal_sdk_dists)
371+
jvmci_dists = graalDistribution
372+
else:
373+
jvmci_dists = graalDistribution + graal_sdk_dists
374+
351375
# Create native-image layout for compiler & jvmci parts
352-
native_image_layout_dists(join('lib', 'jvmci'), graalDistribution)
353-
jdk_config = mx.get_jdk()
354-
jvmci_path = join(jdk_config.home, 'jre', 'lib', 'jvmci')
355-
if os.path.isdir(jvmci_path):
356-
for symlink_name in os.listdir(jvmci_path):
357-
symlink_or_copy(join(jvmci_path, symlink_name), join(native_image_root, 'lib', 'jvmci', symlink_name))
376+
native_image_layout_dists(join('lib', 'jvmci'), jvmci_dists)
377+
if svm_java80():
378+
jdk_config = mx.get_jdk()
379+
jvmci_path = join(jdk_config.home, 'jre', 'lib', 'jvmci')
380+
if os.path.isdir(jvmci_path):
381+
for symlink_name in os.listdir(jvmci_path):
382+
symlink_or_copy(join(jvmci_path, symlink_name), join(native_image_root, 'lib', 'jvmci', symlink_name))
358383

359384
# Create native-image layout for truffle parts
360385
native_image_layout_dists(join('lib', 'truffle'), ['truffle:TRUFFLE_API', 'truffle:TRUFFLE_NFI'])
@@ -901,6 +926,28 @@ def build(args, vm=None):
901926
if not _host_os_supported():
902927
mx.abort('build: SubstrateVM can be built only on Darwin, Linux and Windows platforms')
903928

929+
graal_compiler_flags_dir = join(mx.dependency('substratevm:com.oracle.svm.driver').dir, 'resources')
930+
931+
def update_if_needed(version_tag, graal_compiler_flags):
932+
flags_filename = 'graal-compiler-flags-' + version_tag + '.config'
933+
flags_path = join(graal_compiler_flags_dir, flags_filename)
934+
flags_contents = '\n'.join(graal_compiler_flags)
935+
needs_update = True
936+
try:
937+
with open(flags_path, 'r') as flags_file:
938+
if flags_file.read() == flags_contents:
939+
needs_update = False
940+
except:
941+
pass
942+
943+
if needs_update:
944+
with open(flags_path, 'w') as f:
945+
print('Write file ' + flags_path)
946+
f.write(flags_contents)
947+
948+
for version_tag in GRAAL_COMPILER_FLAGS_MAP:
949+
update_if_needed(version_tag, GRAAL_COMPILER_FLAGS_BASE + GRAAL_COMPILER_FLAGS_MAP[version_tag])
950+
904951
orig_command_build(args, vm)
905952

906953

@@ -918,8 +965,11 @@ def native_image_on_jvm(args, **kwargs):
918965
driver_cp = list(itertools.chain.from_iterable(glob.glob(cp) for cp in driver_cp))
919966

920967
svm_version = suite.release_version(snapshotSuffix='SNAPSHOT')
921-
run_java(['-Dorg.graalvm.version=' + svm_version, '-Dnative-image.root=' + suite_native_image_root(), '-cp', os.pathsep.join(driver_cp),
922-
mx.dependency('substratevm:SVM_DRIVER').mainClass] + save_args, **kwargs)
968+
run_java([
969+
'-Dorg.graalvm.version=' + svm_version,
970+
'-Dnative-image.root=' + suite_native_image_root(),
971+
'-cp', os.pathsep.join(driver_cp),
972+
mx.dependency('substratevm:SVM_DRIVER').mainClass] + save_args, **kwargs)
923973

924974

925975
@mx.command(suite.name, 'native-unittest')

substratevm/src/com.oracle.svm.driver/src/com/oracle/svm/driver/APIOptionHandler.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,14 @@
3030
import java.util.Arrays;
3131
import java.util.List;
3232
import java.util.Queue;
33+
import java.util.ServiceLoader;
3334
import java.util.SortedMap;
3435
import java.util.TreeMap;
3536
import java.util.function.Consumer;
3637
import java.util.stream.Collectors;
3738

3839
import org.graalvm.compiler.options.OptionDescriptor;
3940
import org.graalvm.compiler.options.OptionDescriptors;
40-
import org.graalvm.compiler.options.OptionsParser;
4141
import org.graalvm.nativeimage.Feature;
4242
import org.graalvm.nativeimage.ImageSingletons;
4343
import org.graalvm.nativeimage.Platform;
@@ -76,11 +76,12 @@ static final class OptionInfo {
7676
if (NativeImage.IS_AOT) {
7777
apiOptions = ImageSingletons.lookup(APIOptionCollector.class).options;
7878
} else {
79-
List<Class<? extends OptionDescriptors>> optionsClasses = new ArrayList<>();
80-
for (OptionDescriptors set : OptionsParser.getOptionsLoader()) {
81-
optionsClasses.add(set.getClass());
79+
List<Class<? extends OptionDescriptors>> optionDescriptorsList = new ArrayList<>();
80+
ServiceLoader<OptionDescriptors> serviceLoader = ServiceLoader.load(OptionDescriptors.class, OptionDescriptors.class.getClassLoader());
81+
for (OptionDescriptors optionDescriptors : serviceLoader) {
82+
optionDescriptorsList.add(optionDescriptors.getClass());
8283
}
83-
apiOptions = extractOptions(optionsClasses);
84+
apiOptions = extractOptions(optionDescriptorsList);
8485
}
8586
}
8687

substratevm/src/com.oracle.svm.driver/src/com/oracle/svm/driver/DefaultOptionHandler.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ public boolean consume(Queue<String> args) {
168168
if (headArg.equals(optimizeOption)) {
169169
NativeImage.showError("The " + optimizeOption + " option should not be followed by a space");
170170
} else {
171-
nativeImage.addPlainImageBuilderArg(NativeImage.oHOptimize + headArg.substring(2));
171+
nativeImage.addPlainImageBuilderArg(nativeImage.oHOptimize + headArg.substring(2));
172172
}
173173
return true;
174174
}
@@ -183,7 +183,7 @@ private void handleJarFileArg(Path filePath) {
183183
if (mainClass == null) {
184184
NativeImage.showError("No main manifest attribute, in " + filePath);
185185
}
186-
nativeImage.addPlainImageBuilderArg(NativeImage.oHClass + mainClass);
186+
nativeImage.addPlainImageBuilderArg(nativeImage.oHClass + mainClass);
187187
String jarFileName = filePath.getFileName().toString();
188188
String jarSuffix = ".jar";
189189
String jarFileNameBase;
@@ -193,7 +193,7 @@ private void handleJarFileArg(Path filePath) {
193193
jarFileNameBase = jarFileName;
194194
}
195195
if (!jarFileNameBase.isEmpty()) {
196-
nativeImage.addPlainImageBuilderArg(NativeImage.oHName + jarFileNameBase);
196+
nativeImage.addPlainImageBuilderArg(nativeImage.oHName + jarFileNameBase);
197197
}
198198
String classPath = mainAttributes.getValue("Class-Path");
199199
/* Missing Class-Path Attribute is tolerable */

substratevm/src/com.oracle.svm.driver/src/com/oracle/svm/driver/MacroOptionHandler.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,12 +78,12 @@ private void applyEnabled(MacroOption.EnabledOption enabledOption) {
7878

7979
String imageName = enabledOption.getProperty("ImageName");
8080
if (imageName != null) {
81-
nativeImage.addPlainImageBuilderArg(NativeImage.oHName + imageName);
81+
nativeImage.addPlainImageBuilderArg(nativeImage.oHName + imageName);
8282
}
8383

8484
String launcherClass = enabledOption.getProperty("LauncherClass");
8585
if (launcherClass != null) {
86-
nativeImage.addPlainImageBuilderArg(NativeImage.oHClass + launcherClass);
86+
nativeImage.addPlainImageBuilderArg(nativeImage.oHClass + launcherClass);
8787
}
8888

8989
enabledOption.forEachPropertyValue("JavaArgs", nativeImage::addImageBuilderJavaArgs);

0 commit comments

Comments
 (0)