diff --git a/make/Bundles.gmk b/make/Bundles.gmk index 8161b3b0362..0b324e7e3f3 100644 --- a/make/Bundles.gmk +++ b/make/Bundles.gmk @@ -185,77 +185,30 @@ endif ifneq ($(filter product-bundles% legacy-bundles, $(MAKECMDGOALS)), ) - SYMBOLS_EXCLUDE_PATTERN := %.debuginfo %.diz %.map - - # There may be files with spaces in the names, so use ShellFindFiles - # explicitly. + # There may be files with spaces in the names, so use ShellFindFiles explicitly. ALL_JDK_FILES := $(call ShellFindFiles, $(JDK_IMAGE_DIR)) - ifneq ($(JDK_IMAGE_DIR), $(JDK_SYMBOLS_IMAGE_DIR)) - ALL_JDK_SYMBOLS_FILES := $(call ShellFindFiles, $(JDK_SYMBOLS_IMAGE_DIR)) - else - ALL_JDK_SYMBOLS_FILES := $(ALL_JDK_FILES) - endif ifneq ($(JDK_IMAGE_DIR), $(JDK_DEMOS_IMAGE_DIR)) ALL_JDK_DEMOS_FILES := $(call ShellFindFiles, $(JDK_DEMOS_IMAGE_DIR)) else ALL_JDK_DEMOS_FILES := $(ALL_JDK_FILES) endif - # Create special filter rules when dealing with unzipped .dSYM directories on - # macosx - ifeq ($(call isTargetOs, macosx), true) - ifeq ($(ZIP_EXTERNAL_DEBUG_SYMBOLS), false) - JDK_SYMBOLS_EXCLUDE_PATTERN := $(addprefix %, \ - $(call containing, .dSYM/, $(patsubst $(JDK_IMAGE_DIR)/%, %, \ - $(ALL_JDK_SYMBOLS_FILES)))) - endif - endif - - # Create special filter rules when dealing with debug symbols on windows - ifeq ($(call isTargetOs, windows), true) - ifeq ($(SHIP_DEBUG_SYMBOLS), ) - JDK_SYMBOLS_EXCLUDE_PATTERN := %.pdb - endif - endif - JDK_BUNDLE_FILES := \ $(filter-out \ - $(JDK_SYMBOLS_EXCLUDE_PATTERN) \ $(JDK_EXTRA_EXCLUDES) \ - $(SYMBOLS_EXCLUDE_PATTERN) \ $(JDK_IMAGE_HOMEDIR)/demo/% \ , \ $(ALL_JDK_FILES) \ ) - JDK_SYMBOLS_BUNDLE_FILES := \ - $(call FindFiles, $(SYMBOLS_IMAGE_DIR)) + JDK_SYMBOLS_BUNDLE_FILES := $(call FindFiles, $(SYMBOLS_IMAGE_DIR)) TEST_DEMOS_BUNDLE_FILES := $(filter $(JDK_DEMOS_IMAGE_HOMEDIR)/demo/%, \ $(ALL_JDK_DEMOS_FILES)) ALL_JRE_FILES := $(call ShellFindFiles, $(JRE_IMAGE_DIR)) - # Create special filter rules when dealing with unzipped .dSYM directories on - # macosx - ifeq ($(OPENJDK_TARGET_OS), macosx) - ifeq ($(ZIP_EXTERNAL_DEBUG_SYMBOLS), false) - JRE_SYMBOLS_EXCLUDE_PATTERN := $(addprefix %, \ - $(call containing, .dSYM/, $(patsubst $(JRE_IMAGE_DIR)/%, %, $(ALL_JRE_FILES)))) - endif - endif - - # Create special filter rules when dealing with debug symbols on windows - ifeq ($(call isTargetOs, windows), true) - ifeq ($(SHIP_DEBUG_SYMBOLS), ) - JRE_SYMBOLS_EXCLUDE_PATTERN := %.pdb - endif - endif - - JRE_BUNDLE_FILES := $(filter-out \ - $(JRE_SYMBOLS_EXCLUDE_PATTERN) \ - $(SYMBOLS_EXCLUDE_PATTERN), \ - $(ALL_JRE_FILES)) + JRE_BUNDLE_FILES := $(ALL_JRE_FILES) ifeq ($(MACOSX_CODESIGN_MODE), hardened) # Macosx release build and code signing available. diff --git a/make/CreateJmods.gmk b/make/CreateJmods.gmk index 3280b24924a..32f107b6bb6 100644 --- a/make/CreateJmods.gmk +++ b/make/CreateJmods.gmk @@ -218,10 +218,14 @@ ifeq ($(call isTargetOs, windows), true) ifeq ($(SHIP_DEBUG_SYMBOLS), ) JMOD_FLAGS += --exclude '**{_the.*,_*.marker*,*.diz,*.pdb,*.map}' else - JMOD_FLAGS += --exclude '**{_the.*,_*.marker*,*.diz,*.map}' + JMOD_FLAGS += --exclude '**{_the.*,_*.marker*,*.map}' endif else - JMOD_FLAGS += --exclude '**{_the.*,_*.marker*,*.diz,*.debuginfo,*.dSYM/**,*.dSYM}' + ifeq ($(SHIP_DEBUG_SYMBOLS), ) + JMOD_FLAGS += --exclude '**{_the.*,_*.marker*,*.diz,*.debuginfo,*.dSYM/**,*.dSYM}' + else + JMOD_FLAGS += --exclude '**{_the.*,_*.marker*}' + endif endif # Unless we are creating a very large module, use the small tool JVM options diff --git a/make/Docs.gmk b/make/Docs.gmk index b105e1d8683..a8d40e078e2 100644 --- a/make/Docs.gmk +++ b/make/Docs.gmk @@ -93,16 +93,19 @@ JAVADOC_DISABLED_DOCLINT_WARNINGS := missing JAVADOC_DISABLED_DOCLINT_PACKAGES := org.w3c.* javax.smartcardio # The initial set of options for javadoc +# -XDaccessInternalAPI is a temporary workaround, see 8373909 JAVADOC_OPTIONS := -use -keywords -notimestamp \ -serialwarn -encoding utf-8 -docencoding utf-8 -breakiterator \ -splitIndex --system none -javafx --expand-requires transitive \ - --override-methods=summary + --override-methods=summary \ + -XDaccessInternalAPI # The reference options must stay stable to allow for comparisons across the # development cycle. REFERENCE_OPTIONS := -XDignore.symbol.file=true -use -keywords -notimestamp \ -serialwarn -encoding utf-8 -breakiterator -splitIndex --system none \ - -html5 -javafx --expand-requires transitive + -html5 -javafx --expand-requires transitive \ + -XDaccessInternalAPI # Should we add DRAFT stamps to the generated javadoc? ifeq ($(VERSION_IS_GA), true) diff --git a/make/autoconf/jdk-options.m4 b/make/autoconf/jdk-options.m4 index bb188778001..87d147d4f07 100644 --- a/make/autoconf/jdk-options.m4 +++ b/make/autoconf/jdk-options.m4 @@ -316,23 +316,36 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_DEBUG_SYMBOLS], AC_MSG_CHECKING([if we should add external native debug symbols to the shipped bundles]) AC_ARG_WITH([external-symbols-in-bundles], [AS_HELP_STRING([--with-external-symbols-in-bundles], - [which type of external native debug symbol information shall be shipped in product bundles (none, public, full) - (e.g. ship full/stripped pdbs on Windows) @<:@none@:>@])]) + [which type of external native debug symbol information shall be shipped with bundles/images (none, public, full). + @<:@none in release builds, full otherwise. --with-native-debug-symbols=external/zipped is a prerequisite. public is only supported on Windows@:>@])], + [], + [with_external_symbols_in_bundles=default]) if test "x$with_external_symbols_in_bundles" = x || test "x$with_external_symbols_in_bundles" = xnone ; then AC_MSG_RESULT([no]) elif test "x$with_external_symbols_in_bundles" = xfull || test "x$with_external_symbols_in_bundles" = xpublic ; then - if test "x$OPENJDK_TARGET_OS" != xwindows ; then - AC_MSG_ERROR([--with-external-symbols-in-bundles currently only works on windows!]) - elif test "x$COPY_DEBUG_SYMBOLS" != xtrue ; then - AC_MSG_ERROR([--with-external-symbols-in-bundles only works when --with-native-debug-symbols=external is used!]) - elif test "x$with_external_symbols_in_bundles" = xfull ; then + if test "x$COPY_DEBUG_SYMBOLS" != xtrue ; then + AC_MSG_ERROR([--with-external-symbols-in-bundles only works when --with-native-debug-symbols=external/zipped is used!]) + elif test "x$with_external_symbols_in_bundles" = xpublic && test "x$OPENJDK_TARGET_OS" != xwindows ; then + AC_MSG_ERROR([--with-external-symbols-in-bundles=public is only supported on Windows!]) + fi + + if test "x$with_external_symbols_in_bundles" = xfull ; then AC_MSG_RESULT([full]) SHIP_DEBUG_SYMBOLS=full else AC_MSG_RESULT([public]) SHIP_DEBUG_SYMBOLS=public fi + elif test "x$with_external_symbols_in_bundles" = xdefault ; then + if test "x$DEBUG_LEVEL" = xrelease ; then + AC_MSG_RESULT([no (default)]) + elif test "x$COPY_DEBUG_SYMBOLS" = xtrue ; then + AC_MSG_RESULT([full (default)]) + SHIP_DEBUG_SYMBOLS=full + else + AC_MSG_RESULT([no (default, native debug symbols are not external/zipped)]) + fi else AC_MSG_ERROR([$with_external_symbols_in_bundles is an unknown value for --with-external-symbols-in-bundles]) fi diff --git a/make/jdk/src/classes/build/tools/taglet/JSpec.java b/make/jdk/src/classes/build/tools/taglet/JSpec.java index ca45104e086..d19cdac3122 100644 --- a/make/jdk/src/classes/build/tools/taglet/JSpec.java +++ b/make/jdk/src/classes/build/tools/taglet/JSpec.java @@ -31,10 +31,9 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; +import java.lang.reflect.Field; import javax.lang.model.element.Element; -import javax.lang.model.element.PackageElement; -import javax.lang.model.element.TypeElement; import com.sun.source.doctree.DocTree; import com.sun.source.doctree.LiteralTree; @@ -160,9 +159,10 @@ public String toString(List tags, Element elem) { if (m.find()) { String chapter = m.group("chapter"); String section = m.group("section"); + String rootParent = currentPath().replaceAll("[^/]+", ".."); - String url = String.format("%1$s/../specs/%2$s/%2$s-%3$s.html#%2$s-%3$s%4$s", - docRoot(elem), idPrefix, chapter, section); + String url = String.format("%1$s/specs/%2$s/%2$s-%3$s.html#%2$s-%3$s%4$s", + rootParent, idPrefix, chapter, section); sb.append(" tags, Element elem) { return sb.toString(); } + private static ThreadLocal CURRENT_PATH = null; + + private String currentPath() { + if (CURRENT_PATH == null) { + try { + Field f = Class.forName("jdk.javadoc.internal.doclets.formats.html.HtmlDocletWriter") + .getField("CURRENT_PATH"); + @SuppressWarnings("unchecked") + ThreadLocal tl = (ThreadLocal) f.get(null); + CURRENT_PATH = tl; + } catch (ReflectiveOperationException e) { + throw new RuntimeException("Cannot determine current path", e); + } + } + return CURRENT_PATH.get(); + } private String expand(List trees) { return (new SimpleDocTreeVisitor() { @@ -209,34 +225,4 @@ private String escape(String s) { }).visit(trees, new StringBuilder()).toString(); } - private String docRoot(Element elem) { - switch (elem.getKind()) { - case MODULE: - return ".."; - - case PACKAGE: - PackageElement pe = (PackageElement)elem; - String pkgPart = pe.getQualifiedName() - .toString() - .replace('.', '/') - .replaceAll("[^/]+", ".."); - return pe.getEnclosingElement() != null - ? "../" + pkgPart - : pkgPart; - - case CLASS, ENUM, RECORD, INTERFACE, ANNOTATION_TYPE: - TypeElement te = (TypeElement)elem; - return te.getQualifiedName() - .toString() - .replace('.', '/') - .replaceAll("[^/]+", ".."); - - default: - var enclosing = elem.getEnclosingElement(); - if (enclosing == null) - throw new IllegalArgumentException(elem.getKind().toString()); - return docRoot(enclosing); - } - } - } diff --git a/make/jdk/src/classes/build/tools/taglet/ToolGuide.java b/make/jdk/src/classes/build/tools/taglet/ToolGuide.java index 72a8ab05b3b..ebd8fd10437 100644 --- a/make/jdk/src/classes/build/tools/taglet/ToolGuide.java +++ b/make/jdk/src/classes/build/tools/taglet/ToolGuide.java @@ -31,10 +31,9 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; +import java.lang.reflect.Field; import javax.lang.model.element.Element; -import javax.lang.model.element.PackageElement; -import javax.lang.model.element.TypeElement; import com.sun.source.doctree.DocTree; import com.sun.source.doctree.UnknownBlockTagTree; @@ -68,7 +67,7 @@ public class ToolGuide implements Taglet { static final String TAG_NAME = "toolGuide"; - static final String BASE_URL = "../specs/man"; + static final String BASE_URL = "specs/man"; static final Pattern TAG_PATTERN = Pattern.compile("(?s)(?[A-Za-z0-9]+)\\s*(? + * JLS 5.7.1 Exact Testing Conversions + * @see + * JLS 5.7.2 Unconditionally Exact Testing Conversions + * @see + * JLS 15.20.2 The instanceof Operator * * @implNote Some exactness checks describe a test which can be redirected * safely through one of the existing methods. Those are omitted too (i.e., diff --git a/src/java.base/share/classes/java/util/concurrent/StructuredTaskScope.java b/src/java.base/share/classes/java/util/concurrent/StructuredTaskScope.java index 01bf1158bf6..66ba2c29bb3 100644 --- a/src/java.base/share/classes/java/util/concurrent/StructuredTaskScope.java +++ b/src/java.base/share/classes/java/util/concurrent/StructuredTaskScope.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, 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 @@ -1081,10 +1081,9 @@ static StructuredTaskScope open() { * does not throw then the {@code Joiner}'s {@code result()} method is invoked to * get the result or throw. * - *

This method may only be invoked by the scope owner. Once the result or - * exception outcome is obtained, this method may not be invoked again. The only - * case where the method may be called again is where {@code InterruptedException} - * is thrown while waiting. + *

This method may only be invoked by the scope owner. It may only be invoked once + * to get the result, exception or timeout outcome, unless the previous invocation + * resulted in an {@code InterruptedException} being thrown. * * @return the result * @throws WrongThreadException if the current thread is not the scope owner @@ -1093,8 +1092,11 @@ static StructuredTaskScope open() { * exception from {@link Joiner#result() Joiner.result()} as the cause * @throws TimeoutException if a timeout is set, the timeout expires before or while * waiting, and {@link Joiner#onTimeout() Joiner.onTimeout()} throws this exception - * @throws InterruptedException if interrupted while waiting + * @throws InterruptedException if the current thread is interrupted before or + * while waiting. The current thread's interrupted status is cleared when this + * exception is thrown. * @since 25 + * @see Thread##thread-interruption Thread Interruption */ R join() throws InterruptedException; diff --git a/src/java.base/share/classes/sun/security/util/Password.java b/src/java.base/share/classes/sun/security/util/Password.java index e358bcd95de..02cdcaf53fd 100644 --- a/src/java.base/share/classes/sun/security/util/Password.java +++ b/src/java.base/share/classes/sun/security/util/Password.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2026, 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 @@ -32,6 +32,7 @@ import jdk.internal.access.SharedSecrets; import jdk.internal.io.JdkConsoleImpl; +import jdk.internal.misc.VM; /** * A utility class for reading passwords @@ -65,7 +66,9 @@ public static char[] readPassword(InputStream in, boolean isEchoOn) } consoleBytes = ConsoleHolder.convertToBytes(consoleEntered); in = new ByteArrayInputStream(consoleBytes); - } else if (System.in.available() == 0) { + } else if (in == System.in && VM.isBooted() + && System.in.available() == 0) { + // Warn if reading password from System.in but it's empty. // This may be running in an IDE Run Window or in JShell, // which acts like an interactive console and echoes the // entered password. In this case, print a warning that @@ -73,6 +76,7 @@ public static char[] readPassword(InputStream in, boolean isEchoOn) // it's more likely the input comes from a pipe, such as // "echo password |" or "cat password_file |" where input // will be silently consumed without echoing to the screen. + // Warn only if VM is booted and ResourcesMgr is available. System.err.print(ResourcesMgr.getString ("warning.input.may.be.visible.on.screen")); } diff --git a/src/java.base/windows/classes/sun/nio/ch/WindowsAsynchronousFileChannelImpl.java b/src/java.base/windows/classes/sun/nio/ch/WindowsAsynchronousFileChannelImpl.java index 5df8aef7431..b8fc058bb29 100644 --- a/src/java.base/windows/classes/sun/nio/ch/WindowsAsynchronousFileChannelImpl.java +++ b/src/java.base/windows/classes/sun/nio/ch/WindowsAsynchronousFileChannelImpl.java @@ -452,7 +452,7 @@ public void run() { address = IOUtil.bufferAddress(dst) + pos; } else { buf = Util.getTemporaryDirectBuffer(rem); - address = IOUtil.bufferAddress(buf) + pos; + address = IOUtil.bufferAddress(buf); } boolean pending = false; @@ -640,7 +640,7 @@ public void run() { // temporarily restore position as we don't know how many bytes // will be written src.position(pos); - address = IOUtil.bufferAddress(buf) + pos; + address = IOUtil.bufferAddress(buf); } try { diff --git a/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthProgressBarUI.java b/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthProgressBarUI.java index ee50976bbf4..a300110cced 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthProgressBarUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthProgressBarUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2025, 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 @@ -216,11 +216,9 @@ public void update(Graphics g, JComponent c) { SynthLookAndFeel.update(context, g); - if (((JProgressBar) c).isBorderPainted()) { - context.getPainter().paintProgressBarBackground(context, - g, 0, 0, c.getWidth(), c.getHeight(), - progressBar.getOrientation()); - } + context.getPainter().paintProgressBarBackground(context, + g, 0, 0, c.getWidth(), c.getHeight(), + progressBar.getOrientation()); paint(context, g); } diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/quic/QuicEndpoint.java b/src/java.net.http/share/classes/jdk/internal/net/http/quic/QuicEndpoint.java index b1de5ef4bfd..8bdba21594c 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/quic/QuicEndpoint.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/quic/QuicEndpoint.java @@ -1581,34 +1581,30 @@ private void remapPeerIssuedResetToken(QuicPacketReceiver from, QuicPacketReceiv peerIssuedResetTokens.replaceAll((tok, c) -> c == from ? to : c); } - public void draining(final QuicPacketReceiver connection) { + public void draining(final QuicConnectionImpl connection) { // remap the connection to a DrainingConnection if (closed) return; + + final long idleTimeout = connection.peerPtoMs() * 3; // 3 PTO + connection.localConnectionIdManager().close(); + DrainingConnection draining = new DrainingConnection(connection.connectionIds(), idleTimeout); + // we can ignore stateless reset in the draining state. + remapPeerIssuedResetToken(connection, draining); + connection.connectionIds().forEach((id) -> - connections.compute(id, this::remapDraining)); + connections.compute(id, (i, r) -> remapDraining(i, r, draining))); + draining.startTimer(); assert !connections.containsValue(connection) : connection; } - private DrainingConnection remapDraining(QuicConnectionId id, QuicPacketReceiver conn) { + private DrainingConnection remapDraining(QuicConnectionId id, QuicPacketReceiver conn, DrainingConnection draining) { if (closed) return null; var debugOn = debug.on() && !Thread.currentThread().isVirtual(); - if (conn instanceof ClosingConnection closing) { + if (conn instanceof QuicConnectionImpl || conn instanceof ClosingConnection) { if (debugOn) debug.log("remapping %s to DrainingConnection", id); - final var draining = closing.toDraining(); - remapPeerIssuedResetToken(closing, draining); - draining.startTimer(); - return draining; - } else if (conn instanceof DrainingConnection draining) { - return draining; - } else if (conn instanceof QuicConnectionImpl impl) { - final long idleTimeout = impl.peerPtoMs() * 3; // 3 PTO - impl.localConnectionIdManager().close(); - if (debugOn) debug.log("remapping %s to DrainingConnection", id); - var draining = new DrainingConnection(conn.connectionIds(), idleTimeout); - // we can ignore stateless reset in the draining state. - remapPeerIssuedResetToken(impl, draining); - draining.startTimer(); return draining; + } else if (conn instanceof DrainingConnection d) { + return d; } else if (conn == null) { // connection absent (was probably removed), don't remap to draining if (debugOn) { @@ -1623,30 +1619,32 @@ private DrainingConnection remapDraining(QuicConnectionId id, QuicPacketReceiver protected void closing(QuicConnectionImpl connection, ByteBuffer datagram) { if (closed) return; - ByteBuffer closing = ByteBuffer.allocate(datagram.limit()); - closing.put(datagram.slice()); - closing.flip(); + ByteBuffer closingDatagram = ByteBuffer.allocate(datagram.limit()); + closingDatagram.put(datagram.slice()); + closingDatagram.flip(); + + final long idleTimeout = connection.peerPtoMs() * 3; // 3 PTO + connection.localConnectionIdManager().close(); + var closingConnection = new ClosingConnection(connection.connectionIds(), idleTimeout, datagram); + remapPeerIssuedResetToken(connection, closingConnection); + connection.connectionIds().forEach((id) -> - connections.compute(id, (i, r) -> remapClosing(i, r, closing))); + connections.compute(id, (i, r) -> remapClosing(i, r, closingConnection))); + closingConnection.startTimer(); assert !connections.containsValue(connection) : connection; } - private ClosedConnection remapClosing(QuicConnectionId id, QuicPacketReceiver conn, ByteBuffer datagram) { + private ClosedConnection remapClosing(QuicConnectionId id, QuicPacketReceiver conn, ClosingConnection closingConnection) { if (closed) return null; var debugOn = debug.on() && !Thread.currentThread().isVirtual(); - if (conn instanceof ClosingConnection closing) { + if (conn instanceof QuicConnectionImpl) { + if (debugOn) debug.log("remapping %s to ClosingConnection", id); + return closingConnection; + } else if (conn instanceof ClosingConnection closing) { // we already have a closing datagram, drop the new one return closing; } else if (conn instanceof DrainingConnection draining) { return draining; - } else if (conn instanceof QuicConnectionImpl impl) { - final long idleTimeout = impl.peerPtoMs() * 3; // 3 PTO - impl.localConnectionIdManager().close(); - if (debugOn) debug.log("remapping %s to ClosingConnection", id); - var closing = new ClosingConnection(conn.connectionIds(), idleTimeout, datagram); - remapPeerIssuedResetToken(impl, closing); - closing.startTimer(); - return closing; } else if (conn == null) { // connection absent (was probably removed), don't remap to closing if (debugOn) { @@ -1896,10 +1894,6 @@ protected void dropIncoming(SocketAddress source, ByteBuffer idbytes, HeadersTyp debug.log("ClosingConnection(%s): dropping %s packet", localConnectionIds, headersType); } } - - private DrainingConnection toDraining() { - return new DrainingConnection(localConnectionIds, maxIdleTimeMs); - } } /** diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/BsdCDebugger.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/BsdCDebugger.java index c119e374d66..01a71c8f44c 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/BsdCDebugger.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/BsdCDebugger.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2021, Azul Systems, Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -86,18 +86,22 @@ public CFrame topFrameForThread(ThreadProxy thread) throws DebuggerException { String cpu = dbg.getCPU(); if (cpu.equals("amd64") || cpu.equals("x86_64")) { AMD64ThreadContext context = (AMD64ThreadContext) thread.getContext(); + Address rsp = context.getRegisterAsAddress(AMD64ThreadContext.RSP); + if (rsp == null) return null; Address rbp = context.getRegisterAsAddress(AMD64ThreadContext.RBP); if (rbp == null) return null; Address pc = context.getRegisterAsAddress(AMD64ThreadContext.RIP); if (pc == null) return null; - return new BsdAMD64CFrame(dbg, rbp, pc); + return new BsdAMD64CFrame(dbg, rsp, rbp, pc); } else if (cpu.equals("aarch64")) { AARCH64ThreadContext context = (AARCH64ThreadContext) thread.getContext(); + Address sp = context.getRegisterAsAddress(AARCH64ThreadContext.SP); + if (sp == null) return null; Address fp = context.getRegisterAsAddress(AARCH64ThreadContext.FP); if (fp == null) return null; Address pc = context.getRegisterAsAddress(AARCH64ThreadContext.PC); if (pc == null) return null; - return new BsdAARCH64CFrame(dbg, fp, pc); + return new BsdAARCH64CFrame(dbg, sp, fp, pc); } else { throw new DebuggerException(cpu + " is not yet supported"); } diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/aarch64/BsdAARCH64CFrame.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/aarch64/BsdAARCH64CFrame.java index ebc5c7d716e..185148b39b4 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/aarch64/BsdAARCH64CFrame.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/aarch64/BsdAARCH64CFrame.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2015, Red Hat Inc. * Copyright (c) 2021, Azul Systems, Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -26,15 +26,19 @@ package sun.jvm.hotspot.debugger.bsd.aarch64; +import sun.jvm.hotspot.code.*; import sun.jvm.hotspot.debugger.*; import sun.jvm.hotspot.debugger.aarch64.*; import sun.jvm.hotspot.debugger.bsd.*; import sun.jvm.hotspot.debugger.cdbg.*; import sun.jvm.hotspot.debugger.cdbg.basic.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.runtime.aarch64.*; public final class BsdAARCH64CFrame extends BasicCFrame { - public BsdAARCH64CFrame(BsdDebugger dbg, Address fp, Address pc) { + public BsdAARCH64CFrame(BsdDebugger dbg, Address sp, Address fp, Address pc) { super(dbg.getCDebugger()); + this.sp = sp; this.fp = fp; this.pc = pc; this.dbg = dbg; @@ -54,28 +58,65 @@ public Address localVariableBase() { return fp; } + @Override public CFrame sender(ThreadProxy thread) { - AARCH64ThreadContext context = (AARCH64ThreadContext) thread.getContext(); - Address rsp = context.getRegisterAsAddress(AARCH64ThreadContext.SP); + return sender(thread, null, null, null); + } - if ((fp == null) || fp.lessThan(rsp)) { - return null; + @Override + public CFrame sender(ThreadProxy thread, Address nextSP, Address nextFP, Address nextPC) { + // Check fp + // Skip if both nextFP and nextPC are given - do not need to load from fp. + if (nextFP == null && nextPC == null) { + if (fp == null) { + return null; + } + + // Check alignment of fp + if (dbg.getAddressValue(fp) % (2 * ADDRESS_SIZE) != 0) { + return null; + } } - // Check alignment of fp - if (dbg.getAddressValue(fp) % (2 * ADDRESS_SIZE) != 0) { + if (nextFP == null) { + nextFP = fp.getAddressAt(0); + } + if (nextFP == null) { return null; } - Address nextFP = fp.getAddressAt(0 * ADDRESS_SIZE); - if (nextFP == null || nextFP.lessThanOrEqual(fp)) { - return null; + if (nextPC == null) { + nextPC = fp.getAddressAt(ADDRESS_SIZE); } - Address nextPC = fp.getAddressAt(1 * ADDRESS_SIZE); if (nextPC == null) { return null; } - return new BsdAARCH64CFrame(dbg, nextFP, nextPC); + + if (nextSP == null) { + CodeCache cc = VM.getVM().getCodeCache(); + CodeBlob currentBlob = cc.findBlobUnsafe(pc()); + + // This case is different from HotSpot. See JDK-8371194 for details. + if (currentBlob != null && (currentBlob.isContinuationStub() || currentBlob.isNativeMethod())) { + // Use FP since it should always be valid for these cases. + // TODO: These should be walked as Frames not CFrames. + nextSP = fp.addOffsetTo(2 * ADDRESS_SIZE); + } else { + CodeBlob codeBlob = cc.findBlobUnsafe(nextPC); + boolean useCodeBlob = codeBlob != null && codeBlob.getFrameSize() > 0; + nextSP = useCodeBlob ? nextFP.addOffsetTo((2 * ADDRESS_SIZE) - codeBlob.getFrameSize()) : nextFP; + } + } + if (nextSP == null) { + return null; + } + + return new BsdAARCH64CFrame(dbg, nextSP, nextFP, nextPC); + } + + @Override + public Frame toFrame() { + return new AARCH64Frame(sp, fp, pc); } // package/class internals only diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/amd64/BsdAMD64CFrame.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/amd64/BsdAMD64CFrame.java index 8d0d94b11b7..9077e0007a5 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/amd64/BsdAMD64CFrame.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/amd64/BsdAMD64CFrame.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, 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,10 +29,13 @@ import sun.jvm.hotspot.debugger.bsd.*; import sun.jvm.hotspot.debugger.cdbg.*; import sun.jvm.hotspot.debugger.cdbg.basic.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.runtime.amd64.*; public final class BsdAMD64CFrame extends BasicCFrame { - public BsdAMD64CFrame(BsdDebugger dbg, Address rbp, Address rip) { + public BsdAMD64CFrame(BsdDebugger dbg, Address rsp, Address rbp, Address rip) { super(dbg.getCDebugger()); + this.rsp = rsp; this.rbp = rbp; this.rip = rip; this.dbg = dbg; @@ -52,32 +55,49 @@ public Address localVariableBase() { return rbp; } + @Override public CFrame sender(ThreadProxy thread) { - AMD64ThreadContext context = (AMD64ThreadContext) thread.getContext(); - Address rsp = context.getRegisterAsAddress(AMD64ThreadContext.RSP); + return sender(thread, null, null, null); + } - if ( (rbp == null) || rbp.lessThan(rsp) ) { - return null; + @Override + public CFrame sender(ThreadProxy thread, Address sp, Address fp, Address pc) { + // Check fp + // Skip if both fp and pc are given - do not need to load from rbp. + if (fp == null && pc == null) { + if (rbp == null) { + return null; + } + + // Check alignment of rbp + if (dbg.getAddressValue(rbp) % ADDRESS_SIZE != 0) { + return null; + } } - // Check alignment of rbp - if (dbg.getAddressValue(rbp) % ADDRESS_SIZE != 0) { + Address nextRSP = sp != null ? sp : rbp.addOffsetTo(2 * ADDRESS_SIZE); + if (nextRSP == null) { return null; } - - Address nextRBP = rbp.getAddressAt( 0 * ADDRESS_SIZE); - if (nextRBP == null || nextRBP.lessThanOrEqual(rbp)) { + Address nextRBP = fp != null ? fp : rbp.getAddressAt(0); + if (nextRBP == null) { return null; } - Address nextPC = rbp.getAddressAt( 1 * ADDRESS_SIZE); + Address nextPC = pc != null ? pc : rbp.getAddressAt(ADDRESS_SIZE); if (nextPC == null) { return null; } - return new BsdAMD64CFrame(dbg, nextRBP, nextPC); + return new BsdAMD64CFrame(dbg, nextRSP, nextRBP, nextPC); + } + + @Override + public Frame toFrame() { + return new AMD64Frame(rsp, rbp, rip); } // package/class internals only private static final int ADDRESS_SIZE = 8; + private Address rsp; private Address rip; private Address rbp; private BsdDebugger dbg; diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java index 1f2c4d97dd3..86ac3a892fd 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java @@ -243,8 +243,12 @@ protected HtmlDocletWriter(HtmlConfiguration configuration, DocPath path, boolea if (generating) { writeGenerating(); } + CURRENT_PATH.set(path.getPath()); } + /** Temporary workaround to share current path with taglets, see 8373909 */ + public static final ThreadLocal CURRENT_PATH = new ThreadLocal<>(); + /** * The top-level method to generate and write the page represented by this writer. * diff --git a/src/jdk.jlink/share/man/jlink.md b/src/jdk.jlink/share/man/jlink.md index 0d16e69c9ef..5c77202434c 100644 --- a/src/jdk.jlink/share/man/jlink.md +++ b/src/jdk.jlink/share/man/jlink.md @@ -1,5 +1,5 @@ --- -# Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2017, 2026, 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 @@ -70,6 +70,7 @@ Developers are responsible for updating their custom runtime images. and zip-9 provides the best compression. Default is zip-6. : Deprecated values to be removed in a future release: + - `0`: No compression. Use zip-0 instead. - `1`: Constant string sharing - `2`: ZIP. Use zip-6 instead. @@ -182,6 +183,7 @@ Description and zip-9 provides the best compression. Default is zip-6. : Deprecated values to be removed in a future release: + - Level 0: No compression. Use zip-0 instead. - Level 1: Constant string sharing - Level 2: ZIP. Use zip-6 instead. diff --git a/test/docs/ProblemList.txt b/test/docs/ProblemList.txt index 83693eacbd1..c846678665d 100644 --- a/test/docs/ProblemList.txt +++ b/test/docs/ProblemList.txt @@ -39,5 +39,3 @@ # More than one label is allowed but must be on the same line. # ############################################################################# - -jdk/javadoc/doccheck/checks/jdkCheckLinks.java 8370249 generic-all diff --git a/test/hotspot/jtreg/compiler/c2/TestReplaceNarrowPhiWithBottomPhi.java b/test/hotspot/jtreg/compiler/c2/TestReplaceNarrowPhiWithBottomPhi.java new file mode 100644 index 00000000000..f01698c300f --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/TestReplaceNarrowPhiWithBottomPhi.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2025 IBM Corporation. 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. + */ + +/** + * @test + * @bug 8370200 8374195 + * @requires (os.arch != "ppc64") & (os.arch != "ppc64le") + * @library /test/lib / + * @run driver ${test.main.class} + */ + +package compiler.c2; + +import compiler.lib.ir_framework.*; +import compiler.lib.ir_framework.Test; + +public class TestReplaceNarrowPhiWithBottomPhi { + private int field1; + private volatile int field2; + + static public void main(String[] args) { + TestFramework.run(); + } + + @Test + @IR(counts = { IRNode.PHI, "2" }) + public void test1() { + int j; + for (j = 0; j < 10; j++) { + + } + inlined1(j); + + // Initially, there are 2 memory Phis: one for bottom, one for field1. After loop opts, both + // Phis have the same inputs and the narrower Phi should be replaced by the bottom Phi. + for (int i = 1; i < 100; i *= 2) { + field2 = 42; + } + } + + private void inlined1(int j) { + if (j == 42) { + field1 = 42; + } + } + + @Run(test = "test1") + private void test1Runner() { + test1(); + inlined1(42); + } +} diff --git a/test/hotspot/jtreg/compiler/c2/irTests/TestPushAddThruCast.java b/test/hotspot/jtreg/compiler/c2/irTests/TestPushAddThruCast.java index 7c5fa05f147..3aee78e9d6a 100644 --- a/test/hotspot/jtreg/compiler/c2/irTests/TestPushAddThruCast.java +++ b/test/hotspot/jtreg/compiler/c2/irTests/TestPushAddThruCast.java @@ -44,13 +44,13 @@ public static void main(String[] args) { TestFramework.run(); } - final static int length = RANDOM.nextInt(Integer.MAX_VALUE); - final static long llength = RANDOM.nextInt(Integer.MAX_VALUE); + final static int length = RANDOM.nextInt(5, Integer.MAX_VALUE); + final static long llength = RANDOM.nextInt(2, Integer.MAX_VALUE); static int i; static long l; @Test - @IR(counts = { IRNode.CAST_II, "1" }) + @IR(counts = { IRNode.CAST_II, "2" }) public static int test1() { int j = Objects.checkIndex(i, length); int k = Objects.checkIndex(i + 1, length); @@ -67,7 +67,7 @@ public static void test1_runner() { } @Test - @IR(counts = { IRNode.CAST_LL, "1" }) + @IR(counts = { IRNode.CAST_LL, "2" }) public static long test2() { long j = Objects.checkIndex(l, llength); long k = Objects.checkIndex(l + 1, llength); @@ -82,4 +82,25 @@ public static void test2_runner() { throw new RuntimeException("incorrect result: " + res); } } + + // Test commoning of Casts after loop opts when they are at the same control + @Test + @IR(phase = CompilePhase.ITER_GVN1, counts = { IRNode.CAST_II, "4" }) + @IR(phase = CompilePhase.OPTIMIZE_FINISHED, counts = { IRNode.CAST_II, "2" }) + public static int test3() { + int j = Objects.checkIndex(i - 3, length); + j += Objects.checkIndex(i, length); + j += Objects.checkIndex(i - 2, length); + j += Objects.checkIndex(i - 1, length); + return j; + } + + @Run(test = "test3") + public static void test3_runner() { + i = RANDOM.nextInt(3, length - 1); + int res = test3(); + if (res != i * 4 - 6) { + throw new RuntimeException("incorrect result: " + res + " for i = " + i); + } + } } diff --git a/test/hotspot/jtreg/compiler/igvn/TestNodeWithNoUseAfterPhiIdeal.java b/test/hotspot/jtreg/compiler/igvn/TestNodeWithNoUseAfterPhiIdeal.java new file mode 100644 index 00000000000..b8e2dabc553 --- /dev/null +++ b/test/hotspot/jtreg/compiler/igvn/TestNodeWithNoUseAfterPhiIdeal.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2025 IBM Corporation. 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. + */ + +/** + * @test + * @bug 8373524 + * @summary C2: no reachable node should have no use + * @run main/othervm -Xbatch ${test.main.class} + * @run main ${test.main.class} + */ + +package compiler.igvn; + +public class TestNodeWithNoUseAfterPhiIdeal { + volatile boolean _mutatorToggle; + + boolean _mutatorFlip() { + synchronized (TestNodeWithNoUseAfterPhiIdeal.class) { + _mutatorToggle = new MyBoolean(!_mutatorToggle).v; + return _mutatorToggle; + } + } + + class MyBoolean { + boolean v; + MyBoolean(boolean v) { + int N = 32; + for (int i = 0; i < N; i++) { + this.v = v; + } + } + } + + int[] arr; + void test() { + int limit = 2; + boolean flag1 = _mutatorFlip(); + for (; limit < 4; limit *= 2) { + if (flag1) { + break; + } + } + int zero = 34; + for (int peel = 2; peel < limit; peel++) { + synchronized (TestNodeWithNoUseAfterPhiIdeal.class) { + zero = 0; + } + } + if (zero == 0) { + arr = new int[8]; + } else { + int M = 4; + for (int i = 0; i < M; i++) { + boolean flag2 = _mutatorFlip(); + boolean flag3 = _mutatorFlip(); + if (flag2) { + break; + } + } + } + } + + public static void main(String[] args) { + TestNodeWithNoUseAfterPhiIdeal t = new TestNodeWithNoUseAfterPhiIdeal(); + for (int i = 0; i < 10_000; i++) { + t.test(); + } + } +} diff --git a/test/hotspot/jtreg/compiler/loopopts/TestValidTypeInOverflowProtection.java b/test/hotspot/jtreg/compiler/loopopts/TestValidTypeInOverflowProtection.java new file mode 100644 index 00000000000..39f72b04139 --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopopts/TestValidTypeInOverflowProtection.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2025, 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. + */ + +/* + * @test + * @bug 8373525 + * @summary Test for the check of a valid type (long) for the input variable of overflow protection + * @run main/othervm -Xbatch -XX:-TieredCompilation -XX:CompileCommand=compileonly,compiler.loopopts.TestValidTypeInOverflowProtection::test + * ${test.main.class} + * @run main ${test.main.class} + */ + +package compiler.loopopts; + +import java.util.Vector; + +class TestVector extends Vector { + TestVector(int initialCapacity) { + super(initialCapacity); + } + + Object getElementData() { + return elementData; + } +} + +public class TestValidTypeInOverflowProtection { + int cntr; + int mode; + int value = 533; + int one = 1; + + public static void main(String[] args) { + TestValidTypeInOverflowProtection test = new TestValidTypeInOverflowProtection(); + for (int i = 0; i < 1000; i++) { + test.test(); + } + } + + TestVector nextVector() { + if (cntr == one) { + return null; + } + TestVector vect = new TestVector(value); + if (mode == 2) { + int cap = vect.capacity(); + for (int i = 0; i < cap; i++) { + vect.addElement(new Object()); + } + } + if (++mode == 3) { + mode = cntr++; + } + return vect; + } + + String test() { + cntr = 0; + TestVector vect = nextVector(); + while (vect != null) { + Object backup_array = new Object[vect.size()]; + System.arraycopy(vect.getElementData(), 0, backup_array, 0, vect.size()); + int old_size = vect.size(); + int old_cap = vect.capacity(); + vect.setSize(vect.capacity() + 1); + for (int i = old_size; i < old_cap; i++) { + if (vect.elementAt(i) != null) { + } + } + for (int i = 0; i < new MyInteger(old_size).v; i++) { + } + vect = nextVector(); + } + return null; + } + + class MyInteger { + int v; + + MyInteger(int v) { + int M452 = 4; + int N452 = 8; + for (int i452 = 0; i452 < M452; i452++) { + for (int j452 = 0; j452 < N452; j452++) { + switch (i452) { + case -2: + case 0: + this.v = v; + } + } + } + } + } +} \ No newline at end of file diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/TestAliasingCheckVPointerVariablesNotAvailable.java b/test/hotspot/jtreg/compiler/loopopts/superword/TestAliasingCheckVPointerVariablesNotAvailable.java new file mode 100644 index 00000000000..47540da5648 --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopopts/superword/TestAliasingCheckVPointerVariablesNotAvailable.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2025, 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. + */ + +/* + * @test id=with-flags + * @bug 8373502 + * @summary Test where a VPointer variable was pinned at the pre-loop, but not available at the + * Auto_Vectorization_Check, and so it should not be used for the auto vectorization + * aliasing check, to avoid a bad (circular) graph. + * @run main/othervm + * -XX:CompileCommand=compileonly,*TestAliasingCheckVPointerVariablesNotAvailable::test + * -XX:-TieredCompilation + * -Xcomp + * ${test.main.class} + */ + +/* + * @test id=vanilla + * @bug 8373502 + * @run main ${test.main.class} + */ + +package compiler.loopopts.superword; + +public class TestAliasingCheckVPointerVariablesNotAvailable { + static int iFld; + + public static void main(String[] strArr) { + test(); + } + + static void test() { + int iArr[] = new int[400]; + boolean flag = false; + for (int i = 6; i < 50000; i++) { // Trigger OSR + try { + int x = 234 / iFld; + iFld = iArr[3]; + } catch (ArithmeticException a_e) { + } + for (int j = i; j < 2; j++) { + if (flag) { + iArr[j] = 117; + } else { + iArr[1] = 34; + } + iArr[1] += i; + } + } + } +} diff --git a/test/hotspot/jtreg/compiler/loopstripmining/TestMismatchedMemoryPhis.java b/test/hotspot/jtreg/compiler/loopstripmining/TestMismatchedMemoryPhis.java new file mode 100644 index 00000000000..06980c36537 --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopstripmining/TestMismatchedMemoryPhis.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2025 IBM Corporation. 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. + */ + +/** + * @test + * @bug 8370200 + * @summary Crash: assert(outer->outcnt() >= phis + 2 - be_loads && outer->outcnt() <= phis + 2 + stores + 1) failed: only phis + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions -XX:StressSeed=36200582 -XX:CompileCommand=quiet + * -XX:CompileCommand=compileonly,*TestMismatchedMemoryPhis*::mainTest -XX:-TieredCompilation + * -Xcomp -XX:+StressIGVN -XX:+StressLoopPeeling -XX:PerMethodTrapLimit=0 ${test.main.class} + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions -XX:CompileCommand=quiet + * -XX:CompileCommand=compileonly,*TestMismatchedMemoryPhis*::mainTest -XX:-TieredCompilation + * -Xcomp -XX:+StressIGVN -XX:+StressLoopPeeling -XX:PerMethodTrapLimit=0 ${test.main.class} + * @run main ${test.main.class} + */ + +package compiler.loopstripmining; + +public class TestMismatchedMemoryPhis { + long l; + volatile int iArrFld[]; + + void mainTest() { + int i, i1, i15 = 4, i16 = 4; + for (i = 1; i < 7; ++i) { + l = i; + } + int j = 1; + while (++j < 4) { + try { + i1 = i15 % i16; + i16 = i15; + i1 = 0 % iArrFld[j]; + } catch (ArithmeticException a_e) { + } + } + } + + static public void main(String[] args) { + try { + new TestMismatchedMemoryPhis().mainTest(); + } catch (NullPointerException npe) { + // Expected + } + } +} diff --git a/test/hotspot/jtreg/compiler/rangechecks/TestArrayAccessAboveRCAfterRCCastIIEliminated.java b/test/hotspot/jtreg/compiler/rangechecks/TestArrayAccessAboveRCAfterRCCastIIEliminated.java index 87e87842af3..b31c1425728 100644 --- a/test/hotspot/jtreg/compiler/rangechecks/TestArrayAccessAboveRCAfterRCCastIIEliminated.java +++ b/test/hotspot/jtreg/compiler/rangechecks/TestArrayAccessAboveRCAfterRCCastIIEliminated.java @@ -44,7 +44,6 @@ public class TestArrayAccessAboveRCAfterRCCastIIEliminated { private static volatile int volatileField; public static void main(String[] args) { - int[] array = new int[100]; for (int i = 0; i < 20_000; i++) { test1(9, 10, 1, true); test1(9, 10, 1, false); @@ -72,6 +71,13 @@ public static void main(String[] args) { test12(9, 10, 1, false); test13(9, 10, 1, true); test13(9, 10, 1, false); + test14(8, 0, 1, true); + test14(8, 0, 1, false); + inlined14(0, 0); + test15(8, 0, 1, true); + test15(8, 0, 1, false); + inlined15(0, 0); + } try { test1(-1, 10, 1, true); @@ -125,6 +131,14 @@ public static void main(String[] args) { test13(-1, 10, 1, true); } catch (ArrayIndexOutOfBoundsException arrayIndexOutOfBoundsException) { } + try { + test14(Integer.MAX_VALUE, 10, 1, true); + } catch (ArrayIndexOutOfBoundsException arrayIndexOutOfBoundsException) { + } + try { + test15(Integer.MAX_VALUE, 10, 1, true); + } catch (ArrayIndexOutOfBoundsException arrayIndexOutOfBoundsException) { + } } private static void test1(int i, int j, int flag, boolean flag2) { @@ -468,6 +482,72 @@ private static void test13(int i, int j, int flag, boolean flag2) { } } + // Range check cast type widen after loop opts causes control dependency to be lost + private static void test14(int i, int j, int flag, boolean flag2) { + int l = 0; + for (; l < 10; l++); + j = inlined14(j, l); + int[] array = new int[10]; + notInlined(array); + if (flag == 0) { + } + if (flag2) { + float[] newArray = new float[10]; + newArray[i+j] = 42; // i+j in [0, 9] + float[] otherArray = new float[i+j]; // i+j in [0, max] + if (flag == 0) { + } + intField = array[otherArray.length]; + } else { + float[] newArray = new float[10]; + newArray[i+j] = 42; // i+j in [0, 9] + float[] otherArray = new float[i+j]; // i+j in [0, max] + if (flag == 0) { + } + intField = array[otherArray.length]; + } + } + + private static int inlined14(int j, int l) { + if (l == 10) { + j = 1; + } + return j; + } + + private static void test15(int i, int j, int flag, boolean flag2) { + i = Integer.max(i, Integer.MIN_VALUE + 1); + int l = 0; + for (; l < 10; l++); + j = inlined15(j, l); + int[] array = new int[10]; + notInlined(array); + if (flag == 0) { + } + if (flag2) { + float[] newArray = new float[10]; + newArray[i+j] = 42; // i+j in [0, 9] + float[] otherArray = new float[i+j]; // i+j in [0, max] + if (flag == 0) { + } + intField = array[otherArray.length]; + } else { + float[] newArray = new float[10]; + newArray[i+j] = 42; // i+j in [0, 9] + float[] otherArray = new float[i+j]; // i+j in [0, max] + if (flag == 0) { + } + intField = array[otherArray.length]; + } + } + + private static int inlined15(int j, int l) { + if (l == 10) { + j = Integer.max(j, Integer.MIN_VALUE + 10); + } + return j; + } + private static void notInlined(int[] array) { } diff --git a/test/hotspot/jtreg/compiler/vectorapi/TestVectorOperationsWithPartialSize.java b/test/hotspot/jtreg/compiler/vectorapi/TestVectorOperationsWithPartialSize.java index 6fd20b7e2fb..45f7497f99c 100644 --- a/test/hotspot/jtreg/compiler/vectorapi/TestVectorOperationsWithPartialSize.java +++ b/test/hotspot/jtreg/compiler/vectorapi/TestVectorOperationsWithPartialSize.java @@ -160,7 +160,7 @@ private static int reduceLanes(int init, int[] arr, int vlen, binOpInt f) { return result; } - private static long reduceLanes(long init, long[] arr, int vlen,binOpLong f) { + private static long reduceLanes(long init, long[] arr, int vlen, binOpLong f) { long result = init; for (int i = 0; i < vlen; i++) { result = f.apply(arr[i], result); @@ -216,61 +216,30 @@ public long testAddReductionLong_256() { return result; } - private static void verifyAddReductionFloat(float actual, float[] arr, int vlen) { - float expected = 0.0f; - for (int i = 0; i < vlen; i++) { - expected += arr[i]; - } - // Floating point addition reduction ops may introduce rounding errors. - float ROUNDING_ERROR_FACTOR_ADD = 10.0f; - float tolerance = Math.ulp(expected) * ROUNDING_ERROR_FACTOR_ADD; - if (Math.abs(expected - actual) > tolerance) { - throw new RuntimeException( - "assertEqualsWithTolerance" + - ": expected " + expected + " but was " + actual + - " (tolerance: " + tolerance + ", diff: " + Math.abs(expected - actual) + ")" - ); - } - } - - private static void verifyAddReductionDouble(double actual, double[] arr, int vlen) { - double expected = 0.0; - for (int i = 0; i < vlen; i++) { - expected += arr[i]; - } - // Floating point addition reduction ops may introduce rounding errors. - double ROUNDING_ERROR_FACTOR_ADD = 10.0; - double tolerance = Math.ulp(expected) * ROUNDING_ERROR_FACTOR_ADD; - if (Math.abs(expected - actual) > tolerance) { - throw new RuntimeException( - "assertEqualsWithTolerance" + - ": expected " + expected + " but was " + actual + - " (tolerance: " + tolerance + ", diff: " + Math.abs(expected - actual) + ")" - ); - } - } - + // Because the evaluation order of floating point reduction addition in the Vector + // API is not guaranteed, it is difficult to choose a single tolerance that reliably + // validates results for randomly generated floating‑point inputs. Given that there + // are already extensive jtreg tests under "test/jdk/jdk/incubator/vector" that verify + // the API’s numerical correctness, this test is instead focused solely on checking + // the generated IRs, and deliberately does not assert on the computed result. @Test @IR(counts = {IRNode.VECTOR_MASK_GEN, "1", IRNode.ADD_REDUCTION_VF, "1"}, applyIfCPUFeature = {"sve", "true"}, applyIf = {"MaxVectorSize", ">=32"}) public float testAddReductionFloat() { FloatVector v = FloatVector.fromArray(FSPEC_128, fa, 0); - float result = v.reduceLanes(VectorOperators.ADD); - verifyAddReductionFloat(result, fa, FSPEC_128.length()); - return result; + return v.reduceLanes(VectorOperators.ADD); } - + // Same with above test for float type, this test does not validate the numerical + // result and focuses solely on checking the correctness of the generated IR. @Test @IR(counts = {IRNode.VECTOR_MASK_GEN, "1", IRNode.ADD_REDUCTION_VD, "1"}, applyIfCPUFeature = {"sve", "true"}, applyIf = {"MaxVectorSize", ">=32"}) public double testAddReductionDouble() { DoubleVector v = DoubleVector.fromArray(DSPEC_128, da, 0); - double result = v.reduceLanes(VectorOperators.ADD); - verifyAddReductionDouble(result, da, DSPEC_128.length()); - return result; + return v.reduceLanes(VectorOperators.ADD); } // ============== Reduction Tests - Logical ============== diff --git a/test/hotspot/jtreg/runtime/ClassInitErrors/TestStackOverflowDuringInit.java b/test/hotspot/jtreg/runtime/ClassInitErrors/TestStackOverflowDuringInit.java index 180dc539795..3fee5ab131f 100644 --- a/test/hotspot/jtreg/runtime/ClassInitErrors/TestStackOverflowDuringInit.java +++ b/test/hotspot/jtreg/runtime/ClassInitErrors/TestStackOverflowDuringInit.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, 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,16 +29,25 @@ * cause, even if we can't create the ExceptionInInitializerError * @comment This test could easily be perturbed so don't allow flag settings. * @requires vm.flagless + * @library /test/lib * @comment Run with the smallest stack possible to limit the execution time. * This is the smallest stack that is supported by all platforms. - * @run main/othervm -Xss384K -Xint TestStackOverflowDuringInit + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI TestStackOverflowDuringInit */ import java.io.ByteArrayOutputStream; import java.io.PrintStream; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; +import jdk.test.whitebox.WhiteBox; public class TestStackOverflowDuringInit { + static String expected = "java.lang.NoClassDefFoundError: Could not initialize class TestStackOverflowDuringInit$LongCache"; + static String cause = "Caused by: java.lang.StackOverflowError"; + // The setup for this is somewhat intricate. We need to trigger a // StackOverflowError during execution of the static initializer // for a class, but we need there to be insufficient stack left @@ -88,34 +97,47 @@ static void recurse() { } } - public static void main(String[] args) throws Exception { - String expected = "java.lang.NoClassDefFoundError: Could not initialize class TestStackOverflowDuringInit$LongCache"; - String cause = "Caused by: java.lang.StackOverflowError"; + static class Launcher { + public static void main(String[] args) throws Exception { - // Pre-load, but not initialize, LongCache, else we will - // hit SOE during class loading. - System.out.println("Pre-loading ..."); - Class c = Class.forName("TestStackOverflowDuringInit$LongCache", - false, - TestStackOverflowDuringInit.class.getClassLoader()); - try { - recurse(); - } catch (Throwable ex) { - // ex.printStackTrace(); - verify_stack(ex, expected, cause); + // Pre-load, but not initialize, LongCache, else we will + // hit SOE during class loading. + System.out.println("Pre-loading ..."); + Class c = Class.forName("TestStackOverflowDuringInit$LongCache", + false, + TestStackOverflowDuringInit.class.getClassLoader()); + try { + recurse(); + } catch (Throwable ex) { + // ex.printStackTrace(); + verify_stack(ex, expected, cause); + } } - } - private static void verify_stack(Throwable e, String expected, String cause) throws Exception { - ByteArrayOutputStream byteOS = new ByteArrayOutputStream(); - try (PrintStream printStream = new PrintStream(byteOS)) { - e.printStackTrace(printStream); - } - String stackTrace = byteOS.toString("ASCII"); - System.out.println(stackTrace); - if (!stackTrace.contains(expected) || - (cause != null && !stackTrace.contains(cause))) { - throw new RuntimeException(expected + " and/or " + cause + " missing from stacktrace"); + private static void verify_stack(Throwable e, String expected, String cause) throws Exception { + ByteArrayOutputStream byteOS = new ByteArrayOutputStream(); + try (PrintStream printStream = new PrintStream(byteOS)) { + e.printStackTrace(printStream); + } + String stackTrace = byteOS.toString("ASCII"); + System.out.println(stackTrace); + if (!stackTrace.contains(expected) || + (cause != null && !stackTrace.contains(cause))) { + throw new RuntimeException(expected + " and/or " + cause + " missing from stacktrace"); + } } } + + public static void main(String[] args) throws Exception { + WhiteBox wb = WhiteBox.getWhiteBox(); + long minimumJavaStackSize = wb.getMinimumJavaStackSize(); + ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( + "-Xss" + Long.toString(minimumJavaStackSize), "-Xint", + Launcher.class.getName()); + + OutputAnalyzer analyzer = new OutputAnalyzer(pb.start()); + analyzer.shouldHaveExitValue(0); + analyzer.shouldContain(expected); + analyzer.shouldContain(cause); + } } diff --git a/test/jdk/com/sun/jndi/ldap/LdapPoolTimeoutTest.java b/test/jdk/com/sun/jndi/ldap/LdapPoolTimeoutTest.java index 294e0f5f1a8..b47433ca16f 100644 --- a/test/jdk/com/sun/jndi/ldap/LdapPoolTimeoutTest.java +++ b/test/jdk/com/sun/jndi/ldap/LdapPoolTimeoutTest.java @@ -35,6 +35,8 @@ import javax.naming.Context; import javax.naming.NamingException; import javax.naming.directory.InitialDirContext; + +import java.net.SocketTimeoutException; import java.util.ArrayList; import java.util.Hashtable; import java.util.List; @@ -82,14 +84,10 @@ public void test() throws Exception { env.put(Context.PROVIDER_URL, "ldap://example.com:1234"); try { - futures.add(executorService.submit(() -> { attemptConnect(env); return null; })); - futures.add(executorService.submit(() -> { attemptConnect(env); return null; })); - futures.add(executorService.submit(() -> { attemptConnect(env); return null; })); - futures.add(executorService.submit(() -> { attemptConnect(env); return null; })); - futures.add(executorService.submit(() -> { attemptConnect(env); return null; })); - futures.add(executorService.submit(() -> { attemptConnect(env); return null; })); - futures.add(executorService.submit(() -> { attemptConnect(env); return null; })); - futures.add(executorService.submit(() -> { attemptConnect(env); return null; })); + // launch a few concurrent connection attempts + for (int i = 0; i < 8; i++) { + futures.add(executorService.submit(() -> { attemptConnect(env); return null; })); + } } finally { executorService.shutdown(); } @@ -109,38 +107,55 @@ public void test() throws Exception { private static void attemptConnect(Hashtable env) throws Exception { try { - LdapTimeoutTest.assertCompletion(CONNECT_MILLIS - 1000, - 2 * CONNECT_MILLIS + TOLERANCE, - () -> new InitialDirContext(env)); - } catch (RuntimeException e) { - final String msg = e.getCause() == null ? e.getMessage() : e.getCause().getMessage(); - // assertCompletion may wrap a CommunicationException in an RTE - if (msg != null && - (msg.contains("Network is unreachable") - || msg.contains("No route to host") - || msg.contains("Connection timed out"))) { - // got the expected exception - System.out.println("Received expected RuntimeException message: " + msg); - } else { - // propagate the unexpected exception - throw e; + final InitialDirContext unexpectedCtx = + LdapTimeoutTest.assertCompletion(CONNECT_MILLIS - 1000, + 2 * CONNECT_MILLIS + TOLERANCE, + () -> new InitialDirContext(env)); + throw new RuntimeException("InitialDirContext construction was expected to fail," + + " but returned " + unexpectedCtx); + } catch (Throwable t) { + final NamingException namingEx = findNamingException(t); + if (namingEx != null) { + // found the NamingException, verify it's the right reason + if (namingEx.getCause() instanceof SocketTimeoutException ste) { + // got the expected exception + System.out.println("Received expected SocketTimeoutException: " + ste); + return; + } + // rely on the exception message to verify the expected exception + final String msg = namingEx.getCause() == null + ? namingEx.getMessage() + : namingEx.getCause().getMessage(); + if (msg != null && + (msg.contains("Network is unreachable") + || msg.contains("No route to host") + || msg.contains("Timed out waiting for lock") + || msg.contains("Connect timed out") + || msg.contains("Timeout exceeded while waiting for a connection"))) { + // got the expected exception + System.out.println("Received expected NamingException with message: " + msg); + return; + } } - } catch (NamingException ex) { - final String msg = ex.getCause() == null ? ex.getMessage() : ex.getCause().getMessage(); - if (msg != null && - (msg.contains("Network is unreachable") - || msg.contains("Timed out waiting for lock") - || msg.contains("Connect timed out") - || msg.contains("Timeout exceeded while waiting for a connection"))) { - // got the expected exception - System.out.println("Received expected NamingException message: " + msg); + // unexpected exception, propagate it + if (t instanceof Exception e) { + throw e; } else { - // propagate the unexpected exception - throw ex; + throw new Exception(t); } - } catch (Throwable t) { - throw new RuntimeException(t); } } + // Find and return the NamingException from the given Throwable. Returns null if none found. + private static NamingException findNamingException(final Throwable t) { + Throwable cause = t; + while (cause != null) { + if (cause instanceof NamingException ne) { + return ne; + } + cause = cause.getCause(); + } + return null; + } + } diff --git a/test/jdk/java/lang/Thread/virtual/stress/ParkAfterTimedPark.java b/test/jdk/java/lang/Thread/virtual/stress/ParkAfterTimedPark.java new file mode 100644 index 00000000000..1b173271a79 --- /dev/null +++ b/test/jdk/java/lang/Thread/virtual/stress/ParkAfterTimedPark.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2025, 2026, 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. + */ + +/* + * @test id=parked + * @bug 8369227 + * @summary Stress test untimed park after a timed park when a thread is unparked around the + * same time that the timeout expires. + * @library /test/lib + * @run main/othervm --enable-native-access=ALL-UNNAMED ParkAfterTimedPark 200 false + */ + +/* + * @test id=pinned + * @summary Stress test untimed park, while pinned, and after a timed park when a thread is + * unparked around the same time that the timeout expires. + * @library /test/lib + * @run main/othervm --enable-native-access=ALL-UNNAMED ParkAfterTimedPark 200 true + */ + +import java.time.Instant; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ThreadLocalRandom; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.LockSupport; +import jdk.test.lib.thread.VThreadPinner; + +public class ParkAfterTimedPark { + public static void main(String[] args) throws Exception { + int iterations = (args.length > 0) ? Integer.parseInt(args[0]) : 100; + boolean pinned = (args.length > 1) ? Boolean.parseBoolean(args[1]) : false; + + for (int i = 1; i <= iterations; i++) { + System.out.println(Instant.now() + " => " + i + " of " + iterations); + for (int timeout = 1; timeout <= 10; timeout++) { + test(timeout, true); + } + } + } + + /** + * Creates two virtual threads. The first does a timed-park for the given time, + * then parks in CountDownLatch.await. A second virtual thread unparks the first + * around the same time that the timeout for the first expires. + */ + private static void test(int millis, boolean pinned) throws Exception { + long nanos = TimeUnit.MILLISECONDS.toNanos(millis); + + var finish = new CountDownLatch(1); + + Thread thread1 = Thread.startVirtualThread(() -> { + LockSupport.parkNanos(nanos); + boolean done = false; + while (!done) { + try { + if (pinned) { + VThreadPinner.runPinned(() -> { + finish.await(); + }); + } else { + finish.await(); + } + done = true; + } catch (InterruptedException e) { } + } + }); + + Thread thread2 = Thread.startVirtualThread(() -> { + int delta = ThreadLocalRandom.current().nextInt(millis); + boolean done = false; + while (!done) { + try { + Thread.sleep(millis - delta); + done = true; + } catch (InterruptedException e) { } + } + LockSupport.unpark(thread1); + }); + + // wait for first thread to park before count down + await(thread1, Thread.State.WAITING); + finish.countDown(); + + thread1.join(); + thread2.join(); + } + + /** + * Waits for the given thread to reach a given state. + */ + private static void await(Thread thread, Thread.State expectedState) throws Exception { + Thread.State state = thread.getState(); + while (state != expectedState) { + if (state == Thread.State.TERMINATED) + throw new RuntimeException("Thread has terminated"); + Thread.sleep(10); + state = thread.getState(); + } + } +} diff --git a/test/jdk/java/lang/Thread/virtual/stress/TimedWaitALot.java b/test/jdk/java/lang/Thread/virtual/stress/TimedWaitALot.java index 6a81a7c5fee..704e299ad8b 100644 --- a/test/jdk/java/lang/Thread/virtual/stress/TimedWaitALot.java +++ b/test/jdk/java/lang/Thread/virtual/stress/TimedWaitALot.java @@ -94,17 +94,20 @@ static void test(boolean notify, boolean interrupt, int... timeouts) throws Exce // start thread to Object.notifyAll at around time that the timeout expires if (notify) { - if (ThreadLocalRandom.current().nextBoolean()) { - synchronized (lock) { + executor.submit(() -> { + if (ThreadLocalRandom.current().nextBoolean()) { + synchronized (lock) { + sleepLessThan(timeout); + lock.notifyAll(); + } + } else { sleepLessThan(timeout); - lock.notifyAll(); - } - } else { - sleepLessThan(timeout); - synchronized (lock) { - lock.notifyAll(); + synchronized (lock) { + lock.notifyAll(); + } } - } + return null; + }); } // start thread to interrupt first thread at around time that the timeout expires diff --git a/test/jdk/java/net/httpclient/http3/H3ErrorHandlingTest.java b/test/jdk/java/net/httpclient/http3/H3ErrorHandlingTest.java index 4315fd36de5..bb5aeacbb0c 100644 --- a/test/jdk/java/net/httpclient/http3/H3ErrorHandlingTest.java +++ b/test/jdk/java/net/httpclient/http3/H3ErrorHandlingTest.java @@ -71,6 +71,7 @@ /* * @test + * @bug 8373409 * @key intermittent * @comment testResetControlStream may fail if the client doesn't read the stream type * before the stream is reset, diff --git a/test/jdk/java/nio/channels/AsynchronousFileChannel/BufferPositions.java b/test/jdk/java/nio/channels/AsynchronousFileChannel/BufferPositions.java new file mode 100644 index 00000000000..661696a0581 --- /dev/null +++ b/test/jdk/java/nio/channels/AsynchronousFileChannel/BufferPositions.java @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2025, 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. + */ + +/* + * @test + * @bug 8374382 + * @summary Test AsynchronousFileChannel.read/write with ByteBuffers and varied buffer positions + * @run junit/othervm BufferPositions + */ + +import java.lang.foreign.Arena; +import java.nio.ByteBuffer; +import java.nio.channels.AsynchronousFileChannel; +import java.nio.channels.CompletionHandler; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ThreadLocalRandom; +import java.util.stream.Stream; +import static java.nio.file.StandardOpenOption.*; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import static org.junit.jupiter.api.Assertions.*; + +class BufferPositions { + + private static final int BUF_SIZE = 32; + + /** + * The buffers to test. + */ + static Stream buffers() { + List buffers = List.of( + ByteBuffer.allocate(BUF_SIZE), + ByteBuffer.allocateDirect(BUF_SIZE), + ByteBuffer.wrap(new byte[BUF_SIZE]), + Arena.global().allocate(BUF_SIZE).asByteBuffer(), + Arena.ofAuto().allocate(BUF_SIZE).asByteBuffer(), + Arena.ofShared().allocate(BUF_SIZE).asByteBuffer() + ); + Stream slices = buffers.stream() + .map(bb -> bb.slice(1, bb.capacity() - 1)); + return Stream.concat(buffers.stream(), slices); + } + + /** + * Test using an AsynchronousFileChannel to read bytes into the given buffer. + */ + @ParameterizedTest + @MethodSource("buffers") + void testRead(ByteBuffer bb) throws Exception { + Path file = Files.createTempFile(Path.of("."), "test", "dat"); + + // populate temp file + int size = bb.capacity(); + byte[] contents = new byte[size]; + for (int i = 0; i < size; i++) { + contents[i] = (byte)(i + 1); + } + Files.write(file, contents); + + // read bytes using the buffer as the destination and all possible buffer positions + try (AsynchronousFileChannel ch = AsynchronousFileChannel.open(file, READ)) { + for (int filePosition = 0; filePosition < size; filePosition++) { + for (int bufPos = 0; bufPos < size; bufPos++) { + // read one byte + bb.position(bufPos); + bb.limit(bufPos + 1); + int n = read(ch, filePosition, bb); + assertEquals(1, n); + assertEquals(bufPos + 1, bb.position()); + assertEquals(contents[filePosition], bb.get(bufPos)); + } + } + } + } + + /** + * Test using an AsynchronousFileChannel to write bytes from the given buffer. + */ + @ParameterizedTest + @MethodSource("buffers") + void testWrite(ByteBuffer bb) throws Exception { + Path file = Files.createTempFile(Path.of("."), "test", "dat"); + + // populate temp file, all zeros + int size = bb.capacity(); + byte[] contents = new byte[size]; + Files.write(file, contents); + + // write bytes using the buffer as the source and all possible buffer positions + try (AsynchronousFileChannel ch = AsynchronousFileChannel.open(file, READ, WRITE)) { + for (int filePosition = 0; filePosition < size; filePosition++) { + for (int bufPos = 0; bufPos < size; bufPos++) { + // write one byte + byte b = (byte) ThreadLocalRandom.current().nextInt(); + bb.position(bufPos); + bb.limit(bufPos + 1); + bb.put(bufPos, b); + int n = write(ch, filePosition, bb); + assertEquals(1, n); + assertEquals(bufPos + 1, bb.position()); + assertEquals(b, bb.get(bufPos)); + + // check byte was written at the expected file position + ByteBuffer dst = ByteBuffer.allocate(1); + int nread = ch.read(dst, filePosition).get(); + assertEquals(1, nread); + assertEquals(b, dst.get(0)); + } + } + } + } + + /** + * Reads a byte from a channel into the given buffer, at the given file position. + */ + private int read(AsynchronousFileChannel ch, long position, ByteBuffer bb) throws Exception { + if (ThreadLocalRandom.current().nextBoolean()) { + return ch.read(bb, position).get(); + } else { + var handler = new Handler(); + ch.read(bb, position, null, handler); + return handler.result(); + } + } + + /** + * Writes a byte to a channel from the given buffer, at the given file position. + */ + private int write(AsynchronousFileChannel ch, long position, ByteBuffer bb) throws Exception { + if (ThreadLocalRandom.current().nextBoolean()) { + return ch.write(bb, position).get(); + } else { + var handler = new Handler(); + ch.write(bb, position, null, handler); + return handler.result(); + } + } + + /** + * CompletionHandler that defines a method to await the result of an I/O operation. + */ + private static class Handler implements CompletionHandler { + T result; + Throwable ex; + final CountDownLatch done = new CountDownLatch(1); + + @Override + public void completed(T result, Void att) { + this.result = result; + done.countDown(); + } + + @Override + public void failed(Throwable ex, Void att) { + this.ex = ex; + done.countDown(); + } + + T result() throws InterruptedException { + done.await(); + assertNull(ex); + return result; + } + } +} diff --git a/test/jdk/javax/swing/JProgressBar/TestProgressBarBorder.java b/test/jdk/javax/swing/JProgressBar/TestProgressBarBorder.java deleted file mode 100644 index 06ccfc3b9bf..00000000000 --- a/test/jdk/javax/swing/JProgressBar/TestProgressBarBorder.java +++ /dev/null @@ -1,108 +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. - */ - -import java.io.File; -import java.io.IOException; -import java.lang.reflect.InvocationTargetException; -import java.awt.Graphics; -import java.awt.image.BufferedImage; -import javax.imageio.ImageIO; -import javax.swing.JComponent; -import javax.swing.JProgressBar; -import javax.swing.SwingUtilities; -import javax.swing.UIManager; -import javax.swing.UnsupportedLookAndFeelException; - -import static java.awt.image.BufferedImage.TYPE_INT_RGB; - -/* - * @test - * @bug 8224261 - * @key headful - * @library ../regtesthelpers - * @build Util - * @summary Verifies JProgressBar border is not painted when border - * painting is set to false - * @run main TestProgressBarBorder - */ - -public class TestProgressBarBorder { - public static void main(String[] args) throws Exception { - for (UIManager.LookAndFeelInfo laf : - UIManager.getInstalledLookAndFeels()) { - if (!laf.getName().contains("Nimbus") && !laf.getName().contains("GTK")) { - continue; - } - System.out.println("Testing LAF: " + laf.getName()); - SwingUtilities.invokeAndWait(() -> test(laf)); - } - } - - private static void test(UIManager.LookAndFeelInfo laf) { - setLookAndFeel(laf); - JProgressBar progressBar = createProgressBar(); - progressBar.setBorderPainted(true); - BufferedImage withBorder = paintToImage(progressBar); - progressBar.setBorderPainted(false); - BufferedImage withoutBorder = paintToImage(progressBar); - - boolean equal = Util.compareBufferedImages(withBorder, withoutBorder); - if (equal) { - try { - ImageIO.write(withBorder, "png", new File("withBorder.png")); - ImageIO.write(withoutBorder, "png", new File("withoutBorder.png")); - } catch (IOException ignored) {} - - throw new RuntimeException("JProgressBar border is painted when border " + - "painting is set to false"); - } - } - - private static void setLookAndFeel(UIManager.LookAndFeelInfo laf) { - try { - UIManager.setLookAndFeel(laf.getClassName()); - } catch (UnsupportedLookAndFeelException ignored) { - System.out.println("Unsupported LAF: " + laf.getClassName()); - } catch (ClassNotFoundException | InstantiationException - | IllegalAccessException e) { - throw new RuntimeException(e); - } - } - - private static JProgressBar createProgressBar() { - JProgressBar progressBar = new JProgressBar(); - progressBar.setSize(100, 50); - progressBar.setValue(0); - progressBar.setStringPainted(true); - return progressBar; - } - - private static BufferedImage paintToImage(JComponent content) { - BufferedImage im = new BufferedImage(content.getWidth(), content.getHeight(), - TYPE_INT_RGB); - Graphics g = im.getGraphics(); - content.paint(g); - g.dispose(); - return im; - } -} diff --git a/test/jdk/javax/swing/plaf/nimbus/TestNimbusProgressBarBorder.java b/test/jdk/javax/swing/plaf/nimbus/TestNimbusProgressBarBorder.java new file mode 100644 index 00000000000..f9aade1d24d --- /dev/null +++ b/test/jdk/javax/swing/plaf/nimbus/TestNimbusProgressBarBorder.java @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2025, 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. + */ + +/* + * @test + * @bug 8192888 + * @key headful + * @summary Verifies ProgressBar in Synth L&F renders background + * when border is not painted + * @run main TestNimbusProgressBarBorder + */ + +import java.io.File; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.GridBagLayout; +import java.awt.image.BufferedImage; +import java.awt.Rectangle; +import java.awt.Robot; + +import javax.imageio.ImageIO; + +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JProgressBar; +import javax.swing.UIManager; +import javax.swing.SwingUtilities; + +public class TestNimbusProgressBarBorder { + + private static JFrame frame; + private static JProgressBar progressBar; + private static boolean failure = true; + private static volatile Rectangle rect; + + public static void main(String[] args) throws Exception { + int width = 200; + int height = 100; + try { + Robot robot = new Robot(); + SwingUtilities.invokeAndWait(() -> { + try { + // Set Nimbus L&F + UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel"); + } catch (Exception e) { + throw new RuntimeException(e); + } + frame = new JFrame("Nimbus JProgressBar Test"); + frame.setSize(width, height); + + // ProgressBar setup + progressBar = new JProgressBar(0, 100); + progressBar.setValue(0); + progressBar.setBorderPainted(false); + + JPanel center = new JPanel(new GridBagLayout()); + center.setBackground(Color.WHITE); + center.add(progressBar); + + frame.add(center, BorderLayout.CENTER); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + }); + robot.waitForIdle(); + robot.delay(1000); + SwingUtilities.invokeAndWait(() -> { + rect = progressBar.getBounds(); + }); + + BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); + Graphics2D g2d = (Graphics2D) img.getGraphics(); + g2d.setColor(Color.WHITE); + g2d.fillRect(0, 0, rect.width, rect.height); + progressBar.paint(g2d); + g2d.dispose(); + + robot.waitForIdle(); + robot.delay(100); + + for (int x = 10; x < (10 + rect.width / 2); x++) { + for (int y = 10; y < (10 + rect.height / 2); y++) { + Color col = new Color(img.getRGB(x, y)); + if (!col.equals(Color.WHITE)) { + failure = false; + break; + } + } + } + if (failure) { + ImageIO.write(img, "png", new File("ProgressBarTest.png")); + throw new RuntimeException("ProgressBar background not drawn"); + } + } finally { + SwingUtilities.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } +} diff --git a/test/jdk/jdk/internal/vm/Continuation/OSRWithManyLocals.java b/test/jdk/jdk/internal/vm/Continuation/OSRWithManyLocals.java new file mode 100644 index 00000000000..2a8d4e91001 --- /dev/null +++ b/test/jdk/jdk/internal/vm/Continuation/OSRWithManyLocals.java @@ -0,0 +1,90 @@ +/* +* Copyright (c) 2025, 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. +*/ + +/** +* @test +* @bug 8372591 +* @summary Test freeze/thaw of OSR frame from method with many locals +* @requires vm.continuations +* @requires vm.compMode != "Xint" & vm.compMode != "Xcomp" +* @modules java.base/jdk.internal.vm +* @library /test/lib /test/hotspot/jtreg +* @build jdk.test.whitebox.WhiteBox +* @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox +* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI OSRWithManyLocals +*/ + +import jdk.internal.vm.Continuation; +import jdk.internal.vm.ContinuationScope; + +import jdk.test.lib.Asserts; +import java.lang.reflect.Method; +import jdk.test.whitebox.WhiteBox; + +public class OSRWithManyLocals { + static final WhiteBox wb = WhiteBox.getWhiteBox(); + static final ContinuationScope FOO = new ContinuationScope() {}; + static final Method foo = getMethod("foo"); + + public static void main(String[] args) throws Exception { + runCont(new Continuation(FOO, () -> warmUp())); + runCont(new Continuation(FOO, () -> foo())); + } + + public static void runCont(Continuation cont) { + while (!cont.isDone()) { + cont.run(); + } + } + + public static void warmUp() { + // Trigger compilation of Continuation.yield/yield0 + for (int i = 0; i < 10_000; i++) { + Continuation.yield(FOO); + } + } + + public static void foo() { + // Declare lots of locals so that size of OSR foo + Continuation.yield/yield0 + // frames is less than (foo_sender.unextended_sp() - foo_sender.sp()). + double d1=1,d2=2,d3=3,d4=4,d5=5,d6=6,d7=7,d8=8,d9=9,d10=10,d11=11,d12=12,d13=13,d14=14,d15=15,d16=16,d17=17,d18=18; + double d19=19,d20=20,d21=21,d22=22,d23=23,d24=24,d25=25,d26=26,d27=27,d28=28,d29=29,d30=30,d31=31,d32=32,d33=33,d34=34; + double d35=35,d36=36,d37=37,d38=38,d39=39,d40=40,d41=41,d42=42,d43=43,d44=44,d45=45,d46=46,d47=47,d48=48,d49=49,d50=50; + double d51=51,d52=52,d53=53,d54=54,d55=55,d56=56,d57=57,d58=58,d59=59,d60=60,d61=61,d62=62,d63=63,d64=64,d65=65,d66=66; + double d67=67,d68=68,d69=69,d70=70,d71=71,d72=72,d73=73,d74=74,d75=75,d76=76,d77=77,d78=78,d79=79,d80=80,d81=81,d82=82; + + // Provoke OSR compilation. After we verified the method was compiled keep looping + // until we trigger the _backedge_counter overflow to actually trigger OSR. + for (int i = 0; !wb.isMethodCompiled(foo, true) || i++ < 2_000;) { + } + Continuation.yield(FOO); + } + + static Method getMethod(String method) { + try { + return OSRWithManyLocals.class.getMethod(method); + } catch (Exception e) { + throw new RuntimeException("Exception: couldn't found method " + method + ". " + e.getMessage()); + } + } +} diff --git a/test/jdk/sun/security/util/Password/EmptyIn.java b/test/jdk/sun/security/util/Password/EmptyIn.java new file mode 100644 index 00000000000..b5692b9e7f9 --- /dev/null +++ b/test/jdk/sun/security/util/Password/EmptyIn.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2026, 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 jdk.test.lib.Asserts; +import sun.security.util.Password; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; + +/* + * @test + * @bug 8374555 + * @summary only print warning when reading from System.in + * @modules java.base/sun.security.util + * @library /test/lib + */ +public class EmptyIn { + public static void main(String[] args) throws Exception { + testSystemIn(); + testNotSystemIn(); + } + + static void testSystemIn() throws Exception { + var in = new ByteArrayInputStream(new byte[0]); + var err = new ByteArrayOutputStream(); + var oldErr = System.err; + var oldIn = System.in; + try { + System.setIn(in); + System.setErr(new PrintStream(err)); + Password.readPassword(System.in); + } finally { + System.setIn(oldIn); + System.setErr(oldErr); + } + // Read from System.in. Should warn. + Asserts.assertNotEquals(0, err.size()); + } + + static void testNotSystemIn() throws Exception { + var in = new ByteArrayInputStream(new byte[0]); + var err = new ByteArrayOutputStream(); + var oldErr = System.err; + try { + System.setErr(new PrintStream(err)); + Password.readPassword(in); + } finally { + System.setErr(oldErr); + } + // Not read from System.in. Should not warn. + Asserts.assertEQ(0, err.size()); + } +} diff --git a/test/lib/jdk/test/whitebox/WhiteBox.java b/test/lib/jdk/test/whitebox/WhiteBox.java index 8e30c089bcb..cc570caef7c 100644 --- a/test/lib/jdk/test/whitebox/WhiteBox.java +++ b/test/lib/jdk/test/whitebox/WhiteBox.java @@ -77,6 +77,7 @@ public long getObjectAddress(Object o) { public native long getVMLargePageSize(); public native long getHeapSpaceAlignment(); public native long getHeapAlignment(); + public native long getMinimumJavaStackSize(); public native boolean shipsFullDebugInfo(); public native boolean shipsPublicDebugInfo();