diff --git a/src/java.base/share/classes/module-info.java b/src/java.base/share/classes/module-info.java index 51e9f981d9f..2fc04de54ac 100644 --- a/src/java.base/share/classes/module-info.java +++ b/src/java.base/share/classes/module-info.java @@ -283,6 +283,7 @@ module java.base { java.security.jgss, java.smartcardio, jdk.charsets, + jdk.jlink, jdk.net; exports sun.net to java.net.http, diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/DefaultImageBuilder.java b/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/DefaultImageBuilder.java index e7be2645967..c5e2f4adc1b 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/DefaultImageBuilder.java +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/DefaultImageBuilder.java @@ -56,6 +56,7 @@ import java.util.function.BiPredicate; import java.util.function.Consumer; import java.util.stream.Stream; +import jdk.internal.util.OperatingSystem; import jdk.tools.jlink.internal.BasicImageWriter; import jdk.tools.jlink.internal.ExecutableImage; import jdk.tools.jlink.internal.Platform; @@ -174,7 +175,11 @@ public final class DefaultImageBuilder implements ImageBuilder { if (value == null) { throw new PluginException("ModuleTarget attribute is missing for java.base module"); } - this.platform = Platform.parsePlatform(value); + try { + this.platform = Platform.parsePlatform(value); + } catch (IllegalArgumentException iae) { + throw new PluginException("ModuleTarget is malformed: " + iae.getMessage()); + } checkResourcePool(files); @@ -490,7 +495,7 @@ public final class DefaultImageBuilder implements ImageBuilder { } private boolean isWindows() { - return platform.os() == Platform.OperatingSystem.WINDOWS; + return platform.os() == OperatingSystem.WINDOWS; } /** @@ -563,37 +568,6 @@ public final class DefaultImageBuilder implements ImageBuilder { } } - public static ExecutableImage getExecutableImage(Path root) { - Path binDir = root.resolve(BIN_DIRNAME); - if (Files.exists(binDir.resolve("java")) || - Files.exists(binDir.resolve("java.exe"))) { - return new DefaultExecutableImage(root, retrieveModules(root), Platform.UNKNOWN); - } - return null; - } - - private static Set retrieveModules(Path root) { - Path releaseFile = root.resolve("release"); - Set modules = new HashSet<>(); - if (Files.exists(releaseFile)) { - Properties release = new Properties(); - try (FileInputStream fi = new FileInputStream(releaseFile.toFile())) { - release.load(fi); - } catch (IOException ex) { - System.err.println("Can't read release file " + ex); - } - String mods = release.getProperty("MODULES"); - if (mods != null) { - String[] arr = mods.substring(1, mods.length() - 1).split(" "); - for (String m : arr) { - modules.add(m.trim()); - } - - } - } - return modules; - } - // finds subpaths matching the given criteria (up to 2 levels deep) and applies the given lambda private static void forEachPath(Path dir, BiPredicate matcher, Consumer consumer) throws IOException { try (Stream stream = Files.find(dir, 2, matcher)) { diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/ImageBuilder.java b/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/ImageBuilder.java index 32440d5ba7f..b0162fcad1a 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/ImageBuilder.java +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/ImageBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -80,8 +80,9 @@ public interface ImageBuilder { * Gets the platform of the image. * * @return {@code Platform} object representing the platform of the image + * @throws UnsupportedOperationException if this method is not implemented by the ImageBuilder */ public default Platform getTargetPlatform() { - return Platform.UNKNOWN; + throw new UnsupportedOperationException("Builder does not define getTargetPlatform"); } } diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Platform.java b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Platform.java index a08678455c6..7d06fa33e75 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Platform.java +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Platform.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,68 +24,44 @@ */ package jdk.tools.jlink.internal; +import jdk.internal.util.Architecture; +import jdk.internal.util.OperatingSystem; + import java.util.Locale; /** - * Supported platforms + * Supported OperatingSystem and Architecture. */ public record Platform(OperatingSystem os, Architecture arch) { - public enum OperatingSystem { - WINDOWS, - LINUX, - MACOS, - AIX, - UNKNOWN; - } - - public enum Architecture { - X86, - x64, - ARM, - AARCH64, - UNKNOWN; - } - - public static final Platform UNKNOWN = new Platform(OperatingSystem.UNKNOWN, Architecture.UNKNOWN); - /* * Returns the {@code Platform} based on the platformString of the form -. + * @throws IllegalArgumentException if the delimiter is missing or either OS or + * architecture is not known */ public static Platform parsePlatform(String platformString) { String osName; String archName; int index = platformString.indexOf("-"); if (index < 0) { - osName = platformString; - archName = "UNKNOWN"; - } else { - osName = platformString.substring(0, index); - archName = platformString.substring(index + 1); + throw new IllegalArgumentException("platformString missing delimiter: " + platformString); } - OperatingSystem os; - try { - os = OperatingSystem.valueOf(osName.toUpperCase(Locale.ENGLISH)); - } catch (IllegalArgumentException e) { - os = OperatingSystem.UNKNOWN; - } - Architecture arch = toArch(archName); + osName = platformString.substring(0, index); + OperatingSystem os = OperatingSystem.valueOf(osName.toUpperCase(Locale.ROOT)); + + archName = platformString.substring(index + 1); + // Alias architecture "amd64" to "X64" + archName = archName.replace("amd64", "X64"); + Architecture arch = Architecture.valueOf(archName.toUpperCase(Locale.ROOT)); + return new Platform(os, arch); } /** - * @return true is it's a 64-bit platform - */ - public boolean is64Bit() { - return (arch() == Platform.Architecture.x64 || - arch() == Platform.Architecture.AARCH64); - } - - /** - * Returns the runtime {@code Platform}. + * {@return the runtime {@code Platform}} */ public static Platform runtime() { - return new Platform(runtimeOS(), runtimeArch()); + return new Platform(OperatingSystem.current(), Architecture.current()); } /** @@ -93,43 +69,6 @@ public record Platform(OperatingSystem os, Architecture arch) { */ @Override public String toString() { - return os.toString().toLowerCase() + "-" + arch.toString().toLowerCase(); - } - - /** - * Returns the runtime {@code Platform.OperatingSystem}. - */ - private static OperatingSystem runtimeOS() { - String osName = System.getProperty("os.name").substring(0, 3).toLowerCase(); - OperatingSystem os = switch (osName) { - case "win" -> OperatingSystem.WINDOWS; - case "lin" -> OperatingSystem.LINUX; - case "mac" -> OperatingSystem.MACOS; - case "aix" -> OperatingSystem.AIX; - default -> OperatingSystem.UNKNOWN; - }; - return os; - } - - /** - * Returns the runtime {@code Platform.Architechrure}. - */ - private static Architecture runtimeArch() { - String archName = System.getProperty("os.arch"); - return toArch(archName); - } - - /** - * Returns the {@code Platform.Architecture} based on the archName. - */ - private static Architecture toArch(String archName) { - Architecture arch = switch (archName) { - case "x86" -> Architecture.X86; - case "amd64", "x86_64" -> Architecture.x64; - case "arm" -> Architecture.ARM; - case "aarch64" -> Architecture.AARCH64; - default -> Architecture.UNKNOWN; - }; - return arch; + return os.toString().toLowerCase(Locale.ROOT) + "-" + arch.toString().toLowerCase(Locale.ROOT); } } diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/CDSPlugin.java b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/CDSPlugin.java index a1bee72c255..c131c34b952 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/CDSPlugin.java +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/CDSPlugin.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,8 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.*; +import jdk.internal.util.Architecture; +import jdk.internal.util.OperatingSystem; import jdk.tools.jlink.internal.ExecutableImage; import jdk.tools.jlink.internal.Platform; import jdk.tools.jlink.internal.PostProcessor; @@ -51,7 +53,7 @@ public final class CDSPlugin extends AbstractPlugin implements PostProcessor { private String javaExecutableName() { - if (targetPlatform.os() == Platform.OperatingSystem.WINDOWS) { + if (targetPlatform.os() == OperatingSystem.WINDOWS) { return "java.exe"; } else { return "java"; @@ -100,7 +102,9 @@ public final class CDSPlugin extends AbstractPlugin implements PostProcessor { if (Files.exists(classListPath)) { generateCDSArchive(image,false); - if (targetPlatform.is64Bit()) { + // The targetPlatform is the same as the runtimePlatform. + // For a 64-bit platform, generate the non-compressed oop CDS archive + if (Architecture.is64bit()) { generateCDSArchive(image,true); } System.out.println("Created CDS archive successfully"); diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludeVMPlugin.java b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludeVMPlugin.java index a9cc357787a..a392666597e 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludeVMPlugin.java +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludeVMPlugin.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -245,15 +245,17 @@ public final class ExcludeVMPlugin extends AbstractPlugin { } private static String[] jvmlibs(ResourcePoolModule module) { - String targetPlatform = module.targetPlatform(); - Platform platform = Platform.parsePlatform(targetPlatform); - switch (platform.os()) { - case WINDOWS: - return new String[] { "jvm.dll" }; - case MACOS: - return new String[] { "libjvm.dylib", "libjvm.a" }; - default: - return new String[] { "libjvm.so", "libjvm.a" }; + try { + String targetPlatform = module.targetPlatform(); + Platform platform = Platform.parsePlatform(targetPlatform); + return switch (platform.os()) { + case WINDOWS -> new String[]{"jvm.dll"}; + case MACOS -> new String[]{"libjvm.dylib", "libjvm.a"}; + default -> new String[]{"libjvm.so", "libjvm.a"}; + }; + } catch (IllegalArgumentException iae) { + // For unknown or malformed targetPlatform + return new String[]{"libjvm.so", "libjvm.a"}; } } } diff --git a/test/jdk/tools/jlink/plugins/CDSPluginTest.java b/test/jdk/tools/jlink/plugins/CDSPluginTest.java index f85769645ce..c57c10f9e61 100644 --- a/test/jdk/tools/jlink/plugins/CDSPluginTest.java +++ b/test/jdk/tools/jlink/plugins/CDSPluginTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -82,24 +82,5 @@ public class CDSPluginTest { helper.checkImage(image, module, null, null, new String[] { subDir + "classes.jsa" }); } - - // Simulate different platforms between current runtime and target image. - if (Platform.isLinux()) { - System.out.println("---- Test different platforms scenario ----"); - String jlinkPath = JDKToolFinder.getJDKTool("jlink"); - String[] cmd = {jlinkPath, "--add-modules", "java.base,java.logging", - "-J-Dos.name=windows", "--generate-cds-archive", - "--output", System.getProperty("test.classes") + sep + module + "-tmp"}; - StringBuilder cmdLine = new StringBuilder(); - for (String s : cmd) { - cmdLine.append(s).append(' '); - } - System.out.println("Command line: [" + cmdLine.toString() + "]"); - ProcessBuilder pb = new ProcessBuilder(cmd); - OutputAnalyzer out = new OutputAnalyzer(pb.start()); - System.out.println(" stdout: " + out.getStdout()); - out.shouldMatch("Error: Cannot generate CDS archives: target image platform linux-.*is different from runtime platform windows-.*"); - out.shouldHaveExitValue(1); - } } }