diff --git a/make/modules/java.base/gensrc/GensrcMisc.gmk b/make/modules/java.base/gensrc/GensrcMisc.gmk index b2bae11baa3..e37aa50d41c 100644 --- a/make/modules/java.base/gensrc/GensrcMisc.gmk +++ b/make/modules/java.base/gensrc/GensrcMisc.gmk @@ -50,11 +50,33 @@ $(eval $(call SetupTextFileProcessing, BUILD_VERSION_JAVA, \ @@VENDOR_URL_VM_BUG@@ => $(VENDOR_URL_VM_BUG), \ )) + +# Normalize OPENJDK_TARGET_CPU name to match jdk.internal.util.Architecture enum +ifneq ($(filter $(OPENJDK_TARGET_CPU), ppc64le), ) + OPENJDK_TARGET_ARCH_CANONICAL = ppc64 +else ifneq ($(filter $(OPENJDK_TARGET_CPU), s390x), ) + OPENJDK_TARGET_ARCH_CANONICAL = s390 +else ifneq ($(filter $(OPENJDK_TARGET_CPU), x86_64 amd64), ) + OPENJDK_TARGET_ARCH_CANONICAL = x64 +else + OPENJDK_TARGET_ARCH_CANONICAL := $(OPENJDK_TARGET_CPU) +endif + +# Normalize OPENJDK_TARGET_OS operating system name to match jdk.internal.util.OperatingSystem enum +ifeq ($(OPENJDK_TARGET_OS), macosx) + OPENJDK_TARGET_OS_CANONICAL = macos +else + OPENJDK_TARGET_OS_CANONICAL := $(OPENJDK_TARGET_OS) +endif + $(eval $(call SetupTextFileProcessing, BUILD_PLATFORMPROPERTIES_JAVA, \ - SOURCE_FILES := $(TOPDIR)/src/java.base/share/classes/jdk/internal/util/OperatingSystemProps.java.template, \ - OUTPUT_FILE := $(SUPPORT_OUTPUTDIR)/gensrc/java.base/jdk/internal/util/OperatingSystemProps.java, \ + SOURCE_FILES := $(TOPDIR)/src/java.base/share/classes/jdk/internal/util/PlatformProps.java.template, \ + OUTPUT_FILE := $(SUPPORT_OUTPUTDIR)/gensrc/java.base/jdk/internal/util/PlatformProps.java, \ REPLACEMENTS := \ - @@OPENJDK_TARGET_OS@@ => $(OPENJDK_TARGET_OS), \ + @@OPENJDK_TARGET_OS@@ => $(OPENJDK_TARGET_OS_CANONICAL) ; \ + @@OPENJDK_TARGET_CPU@@ => $(OPENJDK_TARGET_ARCH_CANONICAL) ; \ + @@OPENJDK_TARGET_CPU_ENDIAN@@ => $(OPENJDK_TARGET_CPU_ENDIAN) ; \ + @@OPENJDK_TARGET_CPU_BITS@@ => $(OPENJDK_TARGET_CPU_BITS), \ )) TARGETS += $(BUILD_VERSION_JAVA) $(BUILD_PLATFORMPROPERTIES_JAVA) diff --git a/src/java.base/share/classes/jdk/internal/util/Architecture.java b/src/java.base/share/classes/jdk/internal/util/Architecture.java new file mode 100644 index 00000000000..c303a84caa8 --- /dev/null +++ b/src/java.base/share/classes/jdk/internal/util/Architecture.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.internal.util; + +import jdk.internal.vm.annotation.ForceInline; +import java.util.Locale; + +/** + * System architecture enum values. + * Each architecture, except OTHER, has a matching {@code public static boolean isXXX()} method + * that is true when running on that architecture. + * The values of `OPENJDK_TARGET_CPU` from the build are mapped to the + * architecture values. + */ +public enum Architecture { + OTHER, // An unknown architecture not specifically named + X64, // Represents AMD64 and X86_64 + X86, + AARCH64, + RISCV64, + S390, + PPC64, + ; + + private static Architecture CURRENT_ARCH = initArch(PlatformProps.CURRENT_ARCH_STRING); + + /** + * {@return {@code true} if the current architecture is X64, Aka amd64} + */ + @ForceInline + public static boolean isX64() { + return PlatformProps.TARGET_ARCH_IS_X64; + } + + /** + * {@return {@code true} if the current architecture is X86} + */ + @ForceInline + public static boolean isX86() { + return PlatformProps.TARGET_ARCH_IS_X86; + } + + /** + * {@return {@code true} if the current architecture is RISCV64} + */ + @ForceInline + public static boolean isRISCV64() { + return PlatformProps.TARGET_ARCH_IS_RISCV64; + } + + /** + * {@return {@code true} if the current architecture is S390} + */ + @ForceInline + public static boolean isS390() { + return PlatformProps.TARGET_ARCH_IS_S390; + } + + /** + * {@return {@code true} if the current architecture is PPC64} + * Use {@link #isLittleEndian()} to determine big or little endian. + */ + @ForceInline + public static boolean isPPC64() { + return PlatformProps.TARGET_ARCH_IS_PPC64; + } + + /** + * {@return {@code true} if the current architecture is AARCH64} + */ + @ForceInline + public static boolean isAARCH64() { + return PlatformProps.TARGET_ARCH_IS_AARCH64; + } + + /** + * {@return the current architecture} + */ + public static Architecture current() { + return CURRENT_ARCH; + } + + /** + * {@return {@code true} if the current architecture is 64-bit} + */ + @ForceInline + public static boolean is64bit() { + return PlatformProps.TARGET_ARCH_BITS == 64; + } + + /** + * {@return {@code true} if the current architecture is little-endian} + */ + @ForceInline + public static boolean isLittleEndian() { + return PlatformProps.TARGET_ARCH_LITTLE_ENDIAN; + } + + + /** + * Returns the Architecture of the built architecture. + * Build time names are mapped to respective uppercase enum values. + * Names not recognized are mapped to Architecture.OTHER. + */ + private static Architecture initArch(String archName) { + try { + return Architecture.valueOf(archName.toUpperCase(Locale.ROOT)); + } catch (IllegalArgumentException ile) { + return Architecture.OTHER; + } + } +} diff --git a/src/java.base/share/classes/jdk/internal/util/OperatingSystem.java b/src/java.base/share/classes/jdk/internal/util/OperatingSystem.java index ad90483a65e..3a44fcba0e5 100644 --- a/src/java.base/share/classes/jdk/internal/util/OperatingSystem.java +++ b/src/java.base/share/classes/jdk/internal/util/OperatingSystem.java @@ -22,9 +22,11 @@ */ package jdk.internal.util; -import jdk.internal.util.OperatingSystemProps; +import jdk.internal.util.PlatformProps; import jdk.internal.vm.annotation.ForceInline; +import java.util.Locale; + /** * Enumeration of operating system types and testing for the current OS. * The enumeration can be used to dispatch to OS specific code or values. @@ -80,15 +82,14 @@ public enum OperatingSystem { AIX, ; - // Cache a copy of the array for lightweight indexing - private static final OperatingSystem[] osValues = OperatingSystem.values(); + private static final OperatingSystem CURRENT_OS = initOS(PlatformProps.CURRENT_OS_STRING); /** * {@return {@code true} if built for the Linux operating system} */ @ForceInline public static boolean isLinux() { - return OperatingSystemProps.TARGET_OS_IS_LINUX; + return PlatformProps.TARGET_OS_IS_LINUX; } /** @@ -96,7 +97,7 @@ public enum OperatingSystem { */ @ForceInline public static boolean isMacOS() { - return OperatingSystemProps.TARGET_OS_IS_MACOSX; + return PlatformProps.TARGET_OS_IS_MACOS; } /** @@ -104,7 +105,7 @@ public enum OperatingSystem { */ @ForceInline public static boolean isWindows() { - return OperatingSystemProps.TARGET_OS_IS_WINDOWS; + return PlatformProps.TARGET_OS_IS_WINDOWS; } /** @@ -112,13 +113,23 @@ public enum OperatingSystem { */ @ForceInline public static boolean isAix() { - return OperatingSystemProps.TARGET_OS_IS_AIX; + return PlatformProps.TARGET_OS_IS_AIX; } /** * {@return the current operating system} */ public static OperatingSystem current() { - return osValues[OperatingSystemProps.CURRENT_OS_ORDINAL]; + return CURRENT_OS; } + + /** + * Returns the OperatingSystem of the build. + * Build time names are mapped to respective uppercase enum values. + * Names not recognized throw ExceptionInInitializerError with IllegalArgumentException. + */ + private static OperatingSystem initOS(String osName) { + return OperatingSystem.valueOf(osName.toUpperCase(Locale.ROOT)); + } + } diff --git a/src/java.base/share/classes/jdk/internal/util/OperatingSystemProps.java.template b/src/java.base/share/classes/jdk/internal/util/OperatingSystemProps.java.template deleted file mode 100644 index b7178675e2c..00000000000 --- a/src/java.base/share/classes/jdk/internal/util/OperatingSystemProps.java.template +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package jdk.internal.util; - -/** - * The corresponding source file is generated by GensrcMisc.gmk for java.base. - * @see OperatingSystem - */ -class OperatingSystemProps { - - // Unique integers named to match the build system naming of the build target - // The values must match the ordinals of the respective enum - private static final int TARGET_OS_linux = 0; - private static final int TARGET_OS_macosx = 1; - private static final int TARGET_OS_windows = 2; - private static final int TARGET_OS_aix = 3; - - // Index/ordinal of the current OperatingSystem enum as substituted by the build - static final int CURRENT_OS_ORDINAL = TARGET_OS_@@OPENJDK_TARGET_OS@@; - - // Precomputed booleans for each Operating System - static final boolean TARGET_OS_IS_LINUX = TARGET_OS_@@OPENJDK_TARGET_OS@@ == TARGET_OS_linux; - static final boolean TARGET_OS_IS_MACOSX = TARGET_OS_@@OPENJDK_TARGET_OS@@ == TARGET_OS_macosx; - static final boolean TARGET_OS_IS_WINDOWS = TARGET_OS_@@OPENJDK_TARGET_OS@@ == TARGET_OS_windows; - static final boolean TARGET_OS_IS_AIX = TARGET_OS_@@OPENJDK_TARGET_OS@@ == TARGET_OS_aix; -} diff --git a/src/java.base/share/classes/jdk/internal/util/PlatformProps.java.template b/src/java.base/share/classes/jdk/internal/util/PlatformProps.java.template new file mode 100644 index 00000000000..69a55fdf16c --- /dev/null +++ b/src/java.base/share/classes/jdk/internal/util/PlatformProps.java.template @@ -0,0 +1,59 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.internal.util; + +/** + * The corresponding source file is generated by GensrcMisc.gmk for java.base. + * @see OperatingSystem + * @see Architecture + */ +class PlatformProps { + + // Name of the current OperatingSystem enum as substituted by the build + static final String CURRENT_OS_STRING = "@@OPENJDK_TARGET_OS@@"; + + // Precomputed booleans for each Operating System + static final boolean TARGET_OS_IS_LINUX = "@@OPENJDK_TARGET_OS@@" == "linux"; + static final boolean TARGET_OS_IS_MACOS = "@@OPENJDK_TARGET_OS@@" == "macos"; + static final boolean TARGET_OS_IS_WINDOWS = "@@OPENJDK_TARGET_OS@@" == "windows"; + static final boolean TARGET_OS_IS_AIX = "@@OPENJDK_TARGET_OS@@" == "aix"; + + // The Architecture value for the current architecture + static final String CURRENT_ARCH_STRING = "@@OPENJDK_TARGET_CPU@@"; + + // Architecture.is64Bit() uses this value + static final int TARGET_ARCH_BITS = @@OPENJDK_TARGET_CPU_BITS@@; + + // Architecture.isLittleEndian value from the build + static final boolean TARGET_ARCH_LITTLE_ENDIAN = "@@OPENJDK_TARGET_CPU_ENDIAN@@" == "little"; + + // Precomputed booleans for each Architecture, shared with jdk.internal.util.Architecture + // The variables are named to match the Architecture value names, and + // the values chosen to match the build values. + static final boolean TARGET_ARCH_IS_X64 = "@@OPENJDK_TARGET_CPU@@" == "x64"; + static final boolean TARGET_ARCH_IS_X86 = "@@OPENJDK_TARGET_CPU@@" == "x86"; + static final boolean TARGET_ARCH_IS_AARCH64 = "@@OPENJDK_TARGET_CPU@@" == "aarch64"; + static final boolean TARGET_ARCH_IS_RISCV64 = "@@OPENJDK_TARGET_CPU@@" == "riscv64"; + static final boolean TARGET_ARCH_IS_S390 = "@@OPENJDK_TARGET_CPU@@" == "s390"; + static final boolean TARGET_ARCH_IS_PPC64 = "@@OPENJDK_TARGET_CPU@@" == "ppc64"; +} diff --git a/src/jdk.attach/windows/classes/sun/tools/attach/AttachProviderImpl.java b/src/jdk.attach/windows/classes/sun/tools/attach/AttachProviderImpl.java index 9a12c4bbbff..cd40cdc8266 100644 --- a/src/jdk.attach/windows/classes/sun/tools/attach/AttachProviderImpl.java +++ b/src/jdk.attach/windows/classes/sun/tools/attach/AttachProviderImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -37,16 +37,6 @@ import java.net.UnknownHostException; public class AttachProviderImpl extends HotSpotAttachProvider { public AttachProviderImpl() { - String os = System.getProperty("os.name"); - if (os.startsWith("Windows 9") || os.equals("Windows Me")) { - throw new RuntimeException( - "This provider is not supported on this version of Windows"); - } - String arch = System.getProperty("os.arch"); - if (!arch.equals("x86") && !arch.equals("amd64") && !arch.equals("aarch64")) { - throw new RuntimeException( - "This provider is not supported on this processor architecture"); - } } public String name() { diff --git a/test/jdk/jdk/internal/util/ArchTest.java b/test/jdk/jdk/internal/util/ArchTest.java new file mode 100644 index 00000000000..a6da730a24e --- /dev/null +++ b/test/jdk/jdk/internal/util/ArchTest.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +import java.util.Locale; +import java.util.stream.Stream; + +import jdk.internal.util.Architecture; +import jdk.internal.misc.Unsafe; + +import static jdk.internal.util.Architecture.OTHER; +import static jdk.internal.util.Architecture.AARCH64; +import static jdk.internal.util.Architecture.PPC64; +import static jdk.internal.util.Architecture.RISCV64; +import static jdk.internal.util.Architecture.S390; +import static jdk.internal.util.Architecture.X64; +import static jdk.internal.util.Architecture.X86; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.fail; + +/** + * @test + * @bug 8304915 + * @summary Verify Architecture enum maps to system property os.arch + * @modules java.base/jdk.internal.util + * @modules java.base/jdk.internal.misc + * @run junit ArchTest + */ +public class ArchTest { + private static boolean IS_BIG_ENDIAN = Unsafe.getUnsafe().isBigEndian(); + + private static boolean IS_64BIT_ADDRESS = Unsafe.getUnsafe().addressSize() == 8; + + /** + * Test consistency of System property "os.arch" with Architecture.current(). + */ + @Test + public void nameVsCurrent() { + String osArch = System.getProperty("os.arch").toLowerCase(Locale.ROOT); + System.out.printf("System property os.arch: \"%s\", Architecture.current(): \"%s\"%n", + osArch, Architecture.current()); + Architecture arch = switch (osArch) { + case "x86_64", "amd64" -> X64; + case "x86", "i386" -> X86; + case "aarch64" -> AARCH64; + case "riscv64" -> RISCV64; + case "s390x", "s390" -> S390; + case "ppc64", "ppc64le" -> PPC64; + default -> OTHER; + }; + assertEquals(Architecture.current(), arch, "mismatch in Architecture.current vs " + osArch); + } + + /** + * Test various Architecture enum values vs boolean isXXX() methods. + * @return a stream of arguments for parameterized test + */ + private static Stream archParams() { + return Stream.of( + Arguments.of(X64, Architecture.isX64()), + Arguments.of(X86, Architecture.isX86()), + Arguments.of(AARCH64, Architecture.isAARCH64()), + Arguments.of(RISCV64, Architecture.isRISCV64()), + Arguments.of(S390, Architecture.isS390()), + Arguments.of(PPC64, Architecture.isPPC64()) + ); + } + + @ParameterizedTest + @MethodSource("archParams") + public void isArch(Architecture arch, boolean isArch) { + Architecture current = Architecture.current(); + assertEquals(arch == current, isArch, + "Method is" + arch + "(): returned " + isArch + ", should be (" + arch + " == " + current + ")"); + } + + /** + * Test that Architecture.is64bit() matches Unsafe.addressSize() == 8. + */ + @Test + public void is64BitVsCurrent() { + assertEquals(Architecture.is64bit(), IS_64BIT_ADDRESS, + "Architecture.is64bit() does not match UNSAFE.addressSize() == 8"); + } + + /** + * Test that Architecture.isLittleEndian() == !Unsafe.isBigEndian(). + */ + @Test + public void isLittleEndianVsCurrent() { + assertEquals(Architecture.isLittleEndian(), !IS_BIG_ENDIAN, + "isLittleEndian does not match UNSAFE.isBigEndian()"); + } +}