|
27 | 27 | import static jdk.tools.jlink.internal.TaskHelper.JLINK_BUNDLE; |
28 | 28 |
|
29 | 29 | import java.io.BufferedInputStream; |
| 30 | +import java.io.BufferedReader; |
30 | 31 | import java.io.File; |
31 | 32 | import java.io.IOException; |
32 | 33 | import java.io.InputStream; |
| 34 | +import java.io.InputStreamReader; |
33 | 35 | import java.io.PrintWriter; |
34 | 36 | import java.io.UncheckedIOException; |
35 | 37 | import java.lang.module.Configuration; |
|
56 | 58 | import java.util.List; |
57 | 59 | import java.util.Locale; |
58 | 60 | import java.util.Map; |
| 61 | +import java.util.NoSuchElementException; |
59 | 62 | import java.util.Objects; |
60 | 63 | import java.util.Optional; |
61 | 64 | import java.util.Set; |
@@ -238,6 +241,27 @@ static class OptionsValues { |
238 | 241 | } |
239 | 242 |
|
240 | 243 | public static final String OPTIONS_RESOURCE = "jdk/tools/jlink/internal/options"; |
| 244 | + // Release information stored in the java.base module |
| 245 | + private static final String JDK_RELEASE_RESOURCE = "jdk/internal/misc/resources/release.txt"; |
| 246 | + |
| 247 | + /** |
| 248 | + * Read the release.txt from the module. |
| 249 | + */ |
| 250 | + private static Optional<String> getReleaseInfo(ModuleReference mref) { |
| 251 | + try { |
| 252 | + Optional<InputStream> release = mref.open().open(JDK_RELEASE_RESOURCE); |
| 253 | + |
| 254 | + if (release.isEmpty()) { |
| 255 | + return Optional.empty(); |
| 256 | + } |
| 257 | + |
| 258 | + try (var r = new BufferedReader(new InputStreamReader(release.get()))) { |
| 259 | + return Optional.of(r.readLine()); |
| 260 | + } |
| 261 | + } catch (IOException ioe) { |
| 262 | + throw new UncheckedIOException(ioe); |
| 263 | + } |
| 264 | + } |
241 | 265 |
|
242 | 266 | int run(String[] args) { |
243 | 267 | if (log == null) { |
@@ -410,7 +434,8 @@ private JlinkConfiguration initJlinkConfig() throws BadArgs { |
410 | 434 |
|
411 | 435 | // Sanity check version if we use JMODs |
412 | 436 | if (!isLinkFromRuntime) { |
413 | | - checkJavaBaseVersion(finder); |
| 437 | + assert(finder.find("java.base").isPresent()); |
| 438 | + checkJavaBaseVersion(finder.find("java.base").get()); |
414 | 439 | } |
415 | 440 |
|
416 | 441 | // Determine the roots set |
@@ -561,32 +586,34 @@ public Set<ModuleReference> findAll() { |
561 | 586 | return finder; |
562 | 587 | } |
563 | 588 |
|
| 589 | + private static String getCurrentRuntimeVersion() { |
| 590 | + ModuleReference current = ModuleLayer.boot() |
| 591 | + .configuration() |
| 592 | + .findModule("java.base") |
| 593 | + .get() |
| 594 | + .reference(); |
| 595 | + // This jlink runtime should always have the release.txt |
| 596 | + return getReleaseInfo(current).get(); |
| 597 | + } |
| 598 | + |
564 | 599 | /* |
565 | | - * Checks the version of the module descriptor of java.base for compatibility |
566 | | - * with the current runtime version. |
| 600 | + * Checks the release information of the java.base used for target image |
| 601 | + * for compatibility with the java.base used by jlink. |
567 | 602 | * |
568 | | - * @throws IllegalArgumentException the descriptor of java.base has no |
569 | | - * version or the java.base version is not the same as the current runtime's |
570 | | - * version. |
| 603 | + * @throws IllegalArgumentException If the `java.base` module reference `target` |
| 604 | + * is not compatible with this jlink. |
571 | 605 | */ |
572 | | - private static void checkJavaBaseVersion(ModuleFinder finder) { |
573 | | - assert finder.find("java.base").isPresent(); |
| 606 | + private static void checkJavaBaseVersion(ModuleReference target) { |
| 607 | + String currentRelease = getCurrentRuntimeVersion(); |
574 | 608 |
|
575 | | - // use the version of java.base module, if present, as |
576 | | - // the release version for multi-release JAR files |
577 | | - ModuleDescriptor.Version v = finder.find("java.base").get() |
578 | | - .descriptor().version().orElseThrow(() -> |
579 | | - new IllegalArgumentException("No version in java.base descriptor") |
580 | | - ); |
581 | | - |
582 | | - Runtime.Version version = Runtime.Version.parse(v.toString()); |
583 | | - if (Runtime.version().feature() != version.feature() || |
584 | | - Runtime.version().interim() != version.interim()) { |
585 | | - // jlink version and java.base version do not match. |
586 | | - // We do not (yet) support this mode. |
| 609 | + String targetRelease = getReleaseInfo(target).orElseThrow(() -> new IllegalArgumentException( |
| 610 | + taskHelper.getMessage("err.jlink.version.missing", currentRelease))); |
| 611 | + |
| 612 | + if (!currentRelease.equals(targetRelease)) { |
| 613 | + // Current runtime image and the target runtime image are not compatible build |
587 | 614 | throw new IllegalArgumentException(taskHelper.getMessage("err.jlink.version.mismatch", |
588 | | - Runtime.version().feature(), Runtime.version().interim(), |
589 | | - version.feature(), version.interim())); |
| 615 | + currentRelease, |
| 616 | + targetRelease)); |
590 | 617 | } |
591 | 618 | } |
592 | 619 |
|
|
0 commit comments