|
30 | 30 | import java.io.InputStream;
|
31 | 31 | import java.io.InputStreamReader;
|
32 | 32 | import java.lang.module.FindException;
|
| 33 | +import java.lang.module.ModuleDescriptor; |
33 | 34 | import java.lang.module.ModuleFinder;
|
34 | 35 | import java.lang.module.ModuleReference;
|
35 | 36 | import java.lang.reflect.Method;
|
|
53 | 54 | import java.util.List;
|
54 | 55 | import java.util.ListIterator;
|
55 | 56 | import java.util.Map;
|
| 57 | +import java.util.Objects; |
56 | 58 | import java.util.Optional;
|
57 | 59 | import java.util.Properties;
|
| 60 | +import java.util.Queue; |
58 | 61 | import java.util.Set;
|
59 | 62 | import java.util.StringJoiner;
|
60 | 63 | import java.util.function.BiConsumer;
|
@@ -1598,6 +1601,15 @@ protected int buildImage(List<String> javaArgs, LinkedHashSet<Path> cp, LinkedHa
|
1598 | 1601 | }
|
1599 | 1602 | List<Path> finalImageModulePath = applicationModules.values().stream().toList();
|
1600 | 1603 |
|
| 1604 | + /* |
| 1605 | + * Make sure to add all system modules required by the application that might not be part of |
| 1606 | + * the boot module layer of image builder. If we do not do this, the image builder will fail |
| 1607 | + * to create the image-build module layer, as it will attempt to define system modules to |
| 1608 | + * the host VM. |
| 1609 | + */ |
| 1610 | + Set<String> implicitlyRequiredSystemModules = getImplicitlyRequiredSystemModules(finalImageModulePath); |
| 1611 | + addModules.addAll(implicitlyRequiredSystemModules); |
| 1612 | + |
1601 | 1613 | if (!addModules.isEmpty()) {
|
1602 | 1614 |
|
1603 | 1615 | arguments.add("-D" + ModuleSupport.PROPERTY_IMAGE_EXPLICITLY_ADDED_MODULES + "=" +
|
@@ -1788,6 +1800,41 @@ private Map<String, Path> getModulesFromPath(Collection<Path> modulePath) {
|
1788 | 1800 | return mrefs;
|
1789 | 1801 | }
|
1790 | 1802 |
|
| 1803 | + private Set<String> getImplicitlyRequiredSystemModules(Collection<Path> modulePath) { |
| 1804 | + if (!config.modulePathBuild || modulePath.isEmpty()) { |
| 1805 | + return Set.of(); |
| 1806 | + } |
| 1807 | + |
| 1808 | + ModuleFinder systemModuleFinder = ModuleFinder.ofSystem(); |
| 1809 | + ModuleFinder appModuleFinder = ModuleFinder.of(modulePath.toArray(Path[]::new)); |
| 1810 | + ModuleFinder finder = ModuleFinder.compose(appModuleFinder, systemModuleFinder); |
| 1811 | + Map<String, ModuleReference> modules = finder.findAll().stream() |
| 1812 | + .collect(Collectors.toMap(m -> m.descriptor().name(), m -> m)); |
| 1813 | + |
| 1814 | + Set<String> applicationModulePathRequiredModules = new HashSet<>(); |
| 1815 | + Queue<ModuleReference> discoveryQueue = new ArrayDeque<>(modules.values()); |
| 1816 | + |
| 1817 | + while (!discoveryQueue.isEmpty()) { |
| 1818 | + ModuleReference module = discoveryQueue.poll(); |
| 1819 | + Set<String> requiredModules = getRequiredModules(module); |
| 1820 | + List<ModuleReference> requiredModuleReferences = requiredModules.stream() |
| 1821 | + .map(mn -> modules.getOrDefault(mn, null)) |
| 1822 | + .filter(Objects::nonNull) |
| 1823 | + .toList(); |
| 1824 | + discoveryQueue.addAll(requiredModuleReferences); |
| 1825 | + applicationModulePathRequiredModules.addAll(requiredModules); |
| 1826 | + } |
| 1827 | + |
| 1828 | + applicationModulePathRequiredModules.retainAll(getBuiltInModules()); |
| 1829 | + return applicationModulePathRequiredModules; |
| 1830 | + } |
| 1831 | + |
| 1832 | + private static Set<String> getRequiredModules(ModuleReference mref) { |
| 1833 | + return mref.descriptor().requires().stream() |
| 1834 | + .map(ModuleDescriptor.Requires::name) |
| 1835 | + .collect(Collectors.toSet()); |
| 1836 | + } |
| 1837 | + |
1791 | 1838 | boolean useBundle() {
|
1792 | 1839 | return bundleSupport != null;
|
1793 | 1840 | }
|
|
0 commit comments