Skip to content

Commit

Permalink
8304913: Use OperatingSystem, Architecture, and Version in jlink
Browse files Browse the repository at this point in the history
Reviewed-by: jpai, alanb, mchung
  • Loading branch information
Roger Riggs committed May 15, 2023
1 parent 0f7b1c5 commit 01892f9
Show file tree
Hide file tree
Showing 7 changed files with 50 additions and 148 deletions.
1 change: 1 addition & 0 deletions src/java.base/share/classes/module-info.java
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,7 @@
java.security.jgss,
java.smartcardio,
jdk.charsets,
jdk.jlink,
jdk.net;
exports sun.net to
java.net.http,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
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;
Expand Down Expand Up @@ -174,7 +175,11 @@ public void storeFiles(ResourcePool files) {
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);

Expand Down Expand Up @@ -490,7 +495,7 @@ private String nativeDir(String filename) {
}

private boolean isWindows() {
return platform.os() == Platform.OperatingSystem.WINDOWS;
return platform.os() == OperatingSystem.WINDOWS;
}

/**
Expand Down Expand Up @@ -563,37 +568,6 @@ private static void patchScripts(ExecutableImage img, List<String> args) throws
}
}

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<String> retrieveModules(Path root) {
Path releaseFile = root.resolve("release");
Set<String> 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<Path, BasicFileAttributes> matcher, Consumer<Path> consumer) throws IOException {
try (Stream<Path> stream = Files.find(dir, 2, matcher)) {
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -80,8 +80,9 @@ public default void storeFiles(ResourcePool content) {
* 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");
}
}
99 changes: 19 additions & 80 deletions src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Platform.java
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -24,112 +24,51 @@
*/
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 <operating system>-<arch>.
* @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);
}
OperatingSystem os;
try {
os = OperatingSystem.valueOf(osName.toUpperCase(Locale.ENGLISH));
} catch (IllegalArgumentException e) {
os = OperatingSystem.UNKNOWN;
throw new IllegalArgumentException("platformString missing delimiter: " + platformString);
}
Architecture arch = toArch(archName);
return new Platform(os, arch);
}
osName = platformString.substring(0, index);
OperatingSystem os = OperatingSystem.valueOf(osName.toUpperCase(Locale.ROOT));

/**
* @return true is it's a 64-bit platform
*/
public boolean is64Bit() {
return (arch() == Platform.Architecture.x64 ||
arch() == Platform.Architecture.AARCH64);
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);
}

/**
* 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());
}

/**
* Returns a {@code String} representation of a {@code Platform} in the format of <os>-<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);
}
}
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -29,6 +29,8 @@
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;
Expand All @@ -51,7 +53,7 @@ public CDSPlugin() {


private String javaExecutableName() {
if (targetPlatform.os() == Platform.OperatingSystem.WINDOWS) {
if (targetPlatform.os() == OperatingSystem.WINDOWS) {
return "java.exe";
} else {
return "java";
Expand Down Expand Up @@ -100,7 +102,9 @@ public List<String> process(ExecutableImage image) {
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");
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -245,15 +245,17 @@ private ResourcePoolEntry handleJvmCfgFile(ResourcePoolEntry orig,
}

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"};
}
}
}
21 changes: 1 addition & 20 deletions test/jdk/tools/jlink/plugins/CDSPluginTest.java
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -82,24 +82,5 @@ public static void main(String[] args) throws Throwable {
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);
}
}
}

1 comment on commit 01892f9

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.