diff --git a/make/jdk/src/classes/build/tools/tzdb/TzdbZoneRulesProvider.java b/make/jdk/src/classes/build/tools/tzdb/TzdbZoneRulesProvider.java index 760397255b8..ecca3c69c06 100644 --- a/make/jdk/src/classes/build/tools/tzdb/TzdbZoneRulesProvider.java +++ b/make/jdk/src/classes/build/tools/tzdb/TzdbZoneRulesProvider.java @@ -164,7 +164,8 @@ private void load(List files) throws IOException { } continue; } - if (line.startsWith("Zone")) { // parse Zone line + int token0len = tokens.length > 0 ? tokens[0].length() : line.length(); + if (line.regionMatches(true, 0, "Zone", 0, token0len)) { // parse Zone line String name = tokens[1]; if (excludedZones.contains(name)){ continue; @@ -182,13 +183,13 @@ private void load(List files) throws IOException { if (zLine.parse(tokens, 2)) { openZone = null; } - } else if (line.startsWith("Rule")) { // parse Rule line + } else if (line.regionMatches(true, 0, "Rule", 0, token0len)) { // parse Rule line String name = tokens[1]; if (!rules.containsKey(name)) { rules.put(name, new ArrayList(10)); } rules.get(name).add(new RuleLine().parse(tokens)); - } else if (line.startsWith("Link")) { // parse link line + } else if (line.regionMatches(true, 0, "Link", 0, token0len)) { // parse link line if (tokens.length >= 3) { String realId = tokens[1]; String aliasId = tokens[2]; @@ -304,7 +305,7 @@ private void parse(String[] tokens, int off) { month = parseMonth(tokens[off++]); if (off < tokens.length) { String dayRule = tokens[off++]; - if (dayRule.startsWith("last")) { + if (dayRule.regionMatches(true, 0, "last", 0, 4)) { dayOfMonth = -1; dayOfWeek = parseDayOfWeek(dayRule.substring(4)); adjustForwards = false; @@ -355,11 +356,12 @@ private void parse(String[] tokens, int off) { } int parseYear(String year, int defaultYear) { - switch (year.toLowerCase()) { - case "min": return 1900; - case "max": return Year.MAX_VALUE; - case "only": return defaultYear; - } + int len = year.length(); + + if (year.regionMatches(true, 0, "minimum", 0, len)) return 1900; + if (year.regionMatches(true, 0, "maximum", 0, len)) return Year.MAX_VALUE; + if (year.regionMatches(true, 0, "only", 0, len)) return defaultYear; + return Integer.parseInt(year); } diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index d36eb79194f..dd318b06532 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -1897,7 +1897,10 @@ void os::win32::print_windows_version(outputStream* st) { // - 2016 GA 10/2016 build: 14393 // - 2019 GA 11/2018 build: 17763 // - 2022 GA 08/2021 build: 20348 - if (build_number > 20347) { + // - 2025 Preview build : 26040 + if (build_number > 26039) { + st->print("Server 2025"); + } else if (build_number > 20347) { st->print("Server 2022"); } else if (build_number > 17762) { st->print("Server 2019"); diff --git a/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java b/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java index 18bdc93205a..a722ec3a760 100644 --- a/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java +++ b/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java @@ -2891,7 +2891,7 @@ static final class Canceller implements BiConsumer { final Future f; Canceller(Future f) { this.f = f; } public void accept(Object ignore, Throwable ex) { - if (ex == null && f != null && !f.isDone()) + if (f != null && !f.isDone()) f.cancel(false); } } diff --git a/src/java.base/windows/native/libjava/java_props_md.c b/src/java.base/windows/native/libjava/java_props_md.c index 33cf1abb6b9..bcbdee02976 100644 --- a/src/java.base/windows/native/libjava/java_props_md.c +++ b/src/java.base/windows/native/libjava/java_props_md.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2024, 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 @@ -474,6 +474,8 @@ GetJavaProperties(JNIEnv* env) * where (buildNumber > 17762) * Windows Server 2022 10 0 (!VER_NT_WORKSTATION) * where (buildNumber > 20347) + * Windows Server 2025 10 0 (!VER_NT_WORKSTATION) + * where (buildNumber > 26039) * * This mapping will presumably be augmented as new Windows * versions are released. @@ -557,7 +559,10 @@ GetJavaProperties(JNIEnv* env) case 0: /* Windows server 2019 GA 10/2018 build number is 17763 */ /* Windows server 2022 build number is 20348 */ - if (buildNumber > 20347) { + /* Windows server 2025 Preview build is 26040 */ + if (buildNumber > 26039) { + sprops.os_name = "Windows Server 2025"; + } else if (buildNumber > 20347) { sprops.os_name = "Windows Server 2022"; } else if (buildNumber > 17762) { sprops.os_name = "Windows Server 2019"; diff --git a/test/hotspot/jtreg/compiler/c1/TestTraceLinearScanLevel.java b/test/hotspot/jtreg/compiler/c1/TestTraceLinearScanLevel.java index 2e4ec32869d..46a294388e6 100644 --- a/test/hotspot/jtreg/compiler/c1/TestTraceLinearScanLevel.java +++ b/test/hotspot/jtreg/compiler/c1/TestTraceLinearScanLevel.java @@ -26,8 +26,8 @@ * @bug 8251093 * @summary Sanity check the flag TraceLinearScanLevel with the highest level in a silent HelloWorld program. * - * @requires vm.debug == true & vm.compiler1.enabled - * @run main/othervm -XX:TraceLinearScanLevel=4 compiler.c1.TestTraceLinearScanLevel + * @requires vm.debug == true & vm.compiler1.enabled & vm.compMode != "Xcomp" + * @run main/othervm -Xbatch -XX:TraceLinearScanLevel=4 compiler.c1.TestTraceLinearScanLevel */ package compiler.c1; diff --git a/test/hotspot/jtreg/runtime/cds/appcds/ProhibitedPackage.java b/test/hotspot/jtreg/runtime/cds/appcds/ProhibitedPackage.java index 68e1561f219..77981eb1a78 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/ProhibitedPackage.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/ProhibitedPackage.java @@ -54,7 +54,7 @@ public static void main(String[] args) throws Exception { // will be ignored during dumping. TestCommon.dump(appJar, classlist, "-Xlog:cds") .shouldContain("Dumping") - .shouldContain("[cds] Prohibited package for non-bootstrap classes: java/lang/Prohibited.class") + .shouldContain("Prohibited package for non-bootstrap classes: java/lang/Prohibited.class") .shouldHaveExitValue(0); } diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/stopListening/stoplis001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/stopListening/stoplis001.java index 340c70a2ad1..8006d1684d0 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/stopListening/stoplis001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/stopListening/stoplis001.java @@ -83,7 +83,6 @@ private int runIt(String argv[], PrintStream out) { this.out = out; log = new Log(out, argHandler); - Map cArgs1 = initConnector(argHandler.getTransportPort()); Map cArgs2 = initConnector(null); if ((addr = startListen(cArgs2)) == null) { log.complain("FAILURE: unable to start listening the address " + @@ -93,6 +92,12 @@ private int runIt(String argv[], PrintStream out) { else log.display("TEST: start listening the address " + addr); + // argHandler.getTransportPort() returns a free port (different from the port allocated by startListen(cArgs2)) + Map cArgs1 = initConnector(argHandler.getTransportPort()); + + log.display("cArgs1: " + cArgs1); + log.display("cArgs2: " + cArgs2); + /* Check that an Exception is thrown if ListeningConnector.stopListening has been invoked with argument map different from the one given for a previous ListeningConnector.startListening() invocation */ diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/stopListening/stoplis001/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/stopListening/stoplis001/TEST.properties deleted file mode 100644 index 8b51b2a9115..00000000000 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/stopListening/stoplis001/TEST.properties +++ /dev/null @@ -1,24 +0,0 @@ -# -# Copyright (c) 2018, 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. -# - -exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/stopListening/stoplis001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/stopListening/stoplis001/TestDescription.java index 77da13e38f5..fa68f05d8f5 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/stopListening/stoplis001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ListeningConnector/stopListening/stoplis001/TestDescription.java @@ -40,9 +40,6 @@ * argument map is the same with the one given for the previous * ListeningConnector.startListening() invocation. * - * NOTE: this test is tagged "nonconcurrent" because it uses the default - * "javadebug" shmem file, as do some other tests. - * * @library /vmTestbase * /test/lib * @build nsk.jdi.ListeningConnector.stopListening.stoplis001 diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 7138dff7043..dff28fbfa6e 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -696,6 +696,7 @@ javax/sound/midi/Sequencer/Looping.java 8136897 generic-all # jdk_swing javax/swing/plaf/basic/BasicTextUI/8001470/bug8001470.java 8233177 linux-all,windows-all +javax/swing/plaf/basic/BasicDirectoryModel/LoaderThreadCount.java 8333880 windows-all javax/swing/JFrame/MaximizeWindowTest.java 8321289 linux-all javax/swing/JWindow/ShapedAndTranslucentWindows/ShapedTranslucentPerPixelTranslucentGradient.java 8233582 linux-all diff --git a/test/jdk/java/awt/TrayIcon/TrayIconScalingTest.java b/test/jdk/java/awt/TrayIcon/TrayIconScalingTest.java index 075137ff091..3fa4b8345b1 100644 --- a/test/jdk/java/awt/TrayIcon/TrayIconScalingTest.java +++ b/test/jdk/java/awt/TrayIcon/TrayIconScalingTest.java @@ -85,28 +85,27 @@ public static void main(String[] args) System.out.println("SystemTray is not supported"); return; } - PassFailJFrame passFailJFrame = PassFailJFrame.builder() - .title("TrayIcon Test Instructions") - .instructions(INSTRUCTIONS) - .testTimeOut(8) - .rows(25) - .columns(70) - .screenCapture() - .build(); - createAndShowGUI(); - // does not have a test window, - // hence only the instruction frame is positioned - PassFailJFrame.positionTestWindow(null, - PassFailJFrame.Position.HORIZONTAL); + createAndShowTrayIcon(); + try { - passFailJFrame.awaitAndCheck(); + PassFailJFrame.builder() + .title("TrayIcon Test Instructions") + .instructions(INSTRUCTIONS) + .testTimeOut(8) + .rows(25) + .columns(70) + .screenCapture() + .build() + .awaitAndCheck(); } finally { - tray.remove(icon); + if (tray != null) { + tray.remove(icon); + } } } - private static void createAndShowGUI() { + private static void createAndShowTrayIcon() { ArrayList imageList = new ArrayList<>(); for (int size = 16; size <= 48; size += 4) { imageList.add(createIcon(size)); @@ -120,7 +119,7 @@ private static void createAndShowGUI() { try { tray.add(icon); } catch (AWTException e) { - throw new RuntimeException("Error while adding icon to system tray"); + throw new RuntimeException("Error while adding icon to system tray", e); } } diff --git a/test/jdk/java/util/concurrent/CompletableFuture/CompletableFutureOrTimeoutExceptionallyTest.java b/test/jdk/java/util/concurrent/CompletableFuture/CompletableFutureOrTimeoutExceptionallyTest.java new file mode 100644 index 00000000000..9c6b5b6e5cd --- /dev/null +++ b/test/jdk/java/util/concurrent/CompletableFuture/CompletableFutureOrTimeoutExceptionallyTest.java @@ -0,0 +1,83 @@ +/* + * 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. + */ + +/* + * @test + * @bug 8303742 + * @summary CompletableFuture.orTimeout can leak memory if completed exceptionally + * @modules java.base/java.util.concurrent:open + * @run junit/othervm -Xmx128m CompletableFutureOrTimeoutExceptionallyTest + */ + +import java.time.Duration; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class CompletableFutureOrTimeoutExceptionallyTest { + static final BlockingQueue delayerQueue; + static { + try { + var delayerClass = Class.forName("java.util.concurrent.CompletableFuture$Delayer", + true, + CompletableFuture.class.getClassLoader()); + var delayerField = delayerClass.getDeclaredField("delayer"); + delayerField.setAccessible(true); + delayerQueue = ((ScheduledThreadPoolExecutor)delayerField.get(null)).getQueue(); + } catch (Throwable t) { + throw new ExceptionInInitializerError(t); + } + } + + /** + * Test that orTimeout task is cancelled if the CompletableFuture is completed Exceptionally + */ + @Test + void testOrTimeoutWithCompleteExceptionallyDoesNotLeak() throws InterruptedException { + assertTrue(delayerQueue.peek() == null); + var future = new CompletableFuture<>().orTimeout(12, TimeUnit.HOURS); + assertTrue(delayerQueue.peek() != null); + future.completeExceptionally(new RuntimeException("This is fine")); + while (delayerQueue.peek() != null) { + Thread.sleep(100); + }; + } + + /** + * Test that the completeOnTimeout task is cancelled if the CompletableFuture is completed Exceptionally + */ + @Test + void testCompleteOnTimeoutWithCompleteExceptionallyDoesNotLeak() throws InterruptedException { + assertTrue(delayerQueue.peek() == null); + var future = new CompletableFuture<>().completeOnTimeout(null, 12, TimeUnit.HOURS); + assertTrue(delayerQueue.peek() != null); + future.completeExceptionally(new RuntimeException("This is fine")); + while (delayerQueue.peek() != null) { + Thread.sleep(100); + }; + } +} diff --git a/test/jdk/javax/net/ssl/templates/SSLSocketTemplate.java b/test/jdk/javax/net/ssl/templates/SSLSocketTemplate.java index fa6cccbcdcf..631577fd63c 100644 --- a/test/jdk/javax/net/ssl/templates/SSLSocketTemplate.java +++ b/test/jdk/javax/net/ssl/templates/SSLSocketTemplate.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2024, 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 @@ -273,7 +273,7 @@ protected void doClientSide() throws Exception { configureClientSocket(sslSocket); InetAddress serverAddress = this.serverAddress; InetSocketAddress connectAddress = serverAddress == null - ? new InetSocketAddress("localhost", serverPort) + ? new InetSocketAddress(InetAddress.getLoopbackAddress(), serverPort) : new InetSocketAddress(serverAddress, serverPort); sslSocket.connect(connectAddress, 15000); } catch (IOException ioe) { diff --git a/test/jdk/javax/net/ssl/templates/TLSBase.java b/test/jdk/javax/net/ssl/templates/TLSBase.java index bcddb1147c8..22b13fb494f 100644 --- a/test/jdk/javax/net/ssl/templates/TLSBase.java +++ b/test/jdk/javax/net/ssl/templates/TLSBase.java @@ -31,6 +31,7 @@ import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; +import java.net.InetAddress; import java.net.InetSocketAddress; import java.util.Arrays; import java.util.concurrent.ConcurrentHashMap; @@ -222,7 +223,7 @@ public SSLSocket connect() { try { sslContext = SSLContext.getDefault(); sock = (SSLSocket)sslContext.getSocketFactory().createSocket(); - sock.connect(new InetSocketAddress("localhost", serverPort)); + sock.connect(new InetSocketAddress(InetAddress.getLoopbackAddress(), serverPort)); System.err.println("Client connected using port " + sock.getLocalPort()); name = "client(" + sock.toString() + ")"; diff --git a/test/jdk/javax/swing/plaf/basic/BasicDirectoryModel/LoaderThreadCount.java b/test/jdk/javax/swing/plaf/basic/BasicDirectoryModel/LoaderThreadCount.java new file mode 100644 index 00000000000..770c8f92b26 --- /dev/null +++ b/test/jdk/javax/swing/plaf/basic/BasicDirectoryModel/LoaderThreadCount.java @@ -0,0 +1,277 @@ +/* + * Copyright (c) 2024, 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.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.BrokenBarrierException; +import java.util.concurrent.CyclicBarrier; +import java.util.concurrent.atomic.AtomicReference; +import java.util.stream.LongStream; +import java.util.stream.Stream; + +import javax.swing.JFileChooser; + +/* + * @test + * @bug 8325179 + * @requires os.family == "windows" + * @summary Verifies there's only one BasicDirectoryModel.FilesLoader thread + * at any given moment + * @run main/othervm -Djava.awt.headless=true LoaderThreadCount + */ +public final class LoaderThreadCount extends ThreadGroup { + /** Initial number of files. */ + private static final long NUMBER_OF_FILES = 500; + + /** + * Number of threads running {@code fileChooser.rescanCurrentDirectory()}. + */ + private static final int NUMBER_OF_THREADS = 5; + + /** Number of snapshots with live threads. */ + private static final int SNAPSHOTS = 20; + + /** The barrier to synchronise scanner threads and capturing live threads. */ + private static final CyclicBarrier start = new CyclicBarrier(NUMBER_OF_THREADS + 1); + + /** List of scanner threads. */ + private static final List threads = new ArrayList<>(NUMBER_OF_THREADS); + + /** + * Stores an exception caught by any of the threads. + * If more exceptions are caught, they're added as suppressed exceptions. + */ + private static final AtomicReference exception = + new AtomicReference<>(); + + /** + * Stores an {@code IOException} thrown while removing the files. + */ + private static final AtomicReference ioException = + new AtomicReference<>(); + + + public static void main(String[] args) throws Throwable { + try { + // Start the test in its own thread group to catch and handle + // all thrown exceptions, in particular in + // BasicDirectoryModel.FilesLoader which is created by Swing. + ThreadGroup threadGroup = new LoaderThreadCount(); + Thread runner = new Thread(threadGroup, + LoaderThreadCount::wrapper, + "Test Runner"); + runner.start(); + runner.join(); + } catch (Throwable throwable) { + handleException(throwable); + } + + if (ioException.get() != null) { + System.err.println("An error occurred while removing files:"); + ioException.get().printStackTrace(); + } + + if (exception.get() != null) { + throw exception.get(); + } + } + + private static void wrapper() { + final long timeStart = System.currentTimeMillis(); + try { + runTest(timeStart); + } catch (Throwable throwable) { + handleException(throwable); + } finally { + System.out.printf("Duration: %,d\n", + (System.currentTimeMillis() - timeStart)); + } + } + + private static void runTest(final long timeStart) throws Throwable { + final Path temp = Files.createDirectory(Paths.get("fileChooser-concurrency-" + timeStart)); + + try { + createFiles(temp); + + final JFileChooser fc = new JFileChooser(temp.toFile()); + + threads.addAll(Stream.generate(() -> new Thread(new Scanner(fc))) + .limit(NUMBER_OF_THREADS) + .toList()); + threads.forEach(Thread::start); + + // Create snapshots of live threads + List threadsCapture = + Stream.generate(LoaderThreadCount::getThreadSnapshot) + .limit(SNAPSHOTS) + .toList(); + + threads.forEach(Thread::interrupt); + + List loaderCount = + threadsCapture.stream() + .map(ta -> Arrays.stream(ta) + .filter(Objects::nonNull) + .map(Thread::getName) + .filter(tn -> tn.startsWith("Basic L&F File Loading Thread")) + .count()) + .filter(c -> c > 0) + .toList(); + + if (loaderCount.isEmpty()) { + throw new RuntimeException("Invalid results: no loader threads detected"); + } + + System.out.println("Number of snapshots: " + loaderCount.size()); + + long ones = loaderCount.stream() + .filter(n -> n == 1) + .count(); + long twos = loaderCount.stream() + .filter(n -> n == 2) + .count(); + long count = loaderCount.stream() + .filter(n -> n > 2) + .count(); + System.out.println("Number of snapshots where number of loader threads:"); + System.out.println(" = 1: " + ones); + System.out.println(" = 2: " + twos); + System.out.println(" > 2: " + count); + if (count > loaderCount.size() / 2) { + throw new RuntimeException("Detected " + count + " snapshots " + + "with several loading threads"); + } + } catch (Throwable e) { + threads.forEach(Thread::interrupt); + throw e; + } finally { + deleteFiles(temp); + deleteFile(temp); + } + } + + private static Thread[] getThreadSnapshot() { + try { + start.await(); + // Allow for the scanner threads to initiate re-scanning + Thread.sleep(10); + + Thread[] array = new Thread[Thread.activeCount()]; + Thread.currentThread() + .getThreadGroup() + .enumerate(array, false); + + // Additional delay between captures + Thread.sleep(500); + + return array; + } catch (InterruptedException | BrokenBarrierException e) { + handleException(e); + throw new RuntimeException("getThreadSnapshot is interrupted"); + } + } + + + private LoaderThreadCount() { + super("bdmConcurrency"); + } + + @Override + public void uncaughtException(Thread t, Throwable e) { + handleException(t, e); + } + + private static void handleException(Throwable throwable) { + handleException(Thread.currentThread(), throwable); + } + + private static void handleException(final Thread thread, + final Throwable throwable) { + System.err.println("Exception in " + thread.getName() + ": " + + throwable.getClass() + + (throwable.getMessage() != null + ? ": " + throwable.getMessage() + : "")); + if (!exception.compareAndSet(null, throwable)) { + exception.get().addSuppressed(throwable); + } + threads.stream() + .filter(t -> t != thread) + .forEach(Thread::interrupt); + } + + + private record Scanner(JFileChooser fileChooser) + implements Runnable { + + @Override + public void run() { + try { + do { + start.await(); + fileChooser.rescanCurrentDirectory(); + } while (!Thread.interrupted()); + } catch (InterruptedException | BrokenBarrierException e) { + // Just exit the loop + } + } + } + + private static void createFiles(final Path parent) { + LongStream.range(0, LoaderThreadCount.NUMBER_OF_FILES) + .mapToObj(n -> parent.resolve(n + ".file")) + .forEach(LoaderThreadCount::createFile); + } + + private static void createFile(final Path file) { + try { + Files.createFile(file); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private static void deleteFiles(final Path parent) throws IOException { + try (var stream = Files.walk(parent)) { + stream.filter(p -> p != parent) + .forEach(LoaderThreadCount::deleteFile); + } + } + + private static void deleteFile(final Path file) { + try { + Files.delete(file); + } catch (IOException e) { + if (!ioException.compareAndSet(null, e)) { + ioException.get().addSuppressed(e); + } + } + } +} diff --git a/test/jdk/sun/security/pkcs11/PKCS11Test.java b/test/jdk/sun/security/pkcs11/PKCS11Test.java index ca4a74e1825..046e5558486 100644 --- a/test/jdk/sun/security/pkcs11/PKCS11Test.java +++ b/test/jdk/sun/security/pkcs11/PKCS11Test.java @@ -77,7 +77,7 @@ public abstract class PKCS11Test { // Version of the NSS artifact. This coincides with the version of // the NSS version - private static final String NSS_BUNDLE_VERSION = "3.96"; + private static final String NSS_BUNDLE_VERSION = "3.101"; private static final String NSSLIB = "jpg.tests.jdk.nsslib"; static double nss_version = -1; diff --git a/test/jdk/sun/security/pkcs11/Signature/TestDSAKeyLength.java b/test/jdk/sun/security/pkcs11/Signature/TestDSAKeyLength.java index a2d7f67fa32..b2ab96c90c6 100644 --- a/test/jdk/sun/security/pkcs11/Signature/TestDSAKeyLength.java +++ b/test/jdk/sun/security/pkcs11/Signature/TestDSAKeyLength.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2024, 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 @@ -48,8 +48,12 @@ public static void main(String[] args) throws Exception { @Override protected boolean skipTest(Provider provider) { - if (isNSS(provider) && (getNSSVersion() == 0.0 || getNSSVersion() >= 3.14)) { - System.out.println("Skip testing NSS " + getNSSVersion()); + double version = getNSSVersion(); + String[] versionStrs = Double.toString(version).split("\\."); + int major = Integer.parseInt(versionStrs[0]); + int minor = Integer.parseInt(versionStrs[1]); + if (isNSS(provider) && (version == 0.0 || (major >= 3 && minor >= 14))) { + System.out.println("Skip testing NSS " + version); return true; } diff --git a/test/jdk/sun/util/calendar/zi/RuleRec.java b/test/jdk/sun/util/calendar/zi/RuleRec.java index 6d9d4905d6a..e6e18773d16 100644 --- a/test/jdk/sun/util/calendar/zi/RuleRec.java +++ b/test/jdk/sun/util/calendar/zi/RuleRec.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2024, 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 @@ -168,12 +168,13 @@ static RuleRec parse(StringTokenizer tokens) { rec.toYear = Integer.parseInt(token); } catch (NumberFormatException e) { // it's not integer - if ("min".equals(token) || "minimum".equals(token)) { + int len = token.length(); + if (token.regionMatches(true, 0, "minimum", 0, len)) { rec.fromYear = Zoneinfo.getMinYear(); - } else if ("max".equals(token) || "maximum".equals(token)) { + } else if (token.regionMatches(true, 0, "maximum", 0, len)) { rec.toYear = Integer.MAX_VALUE; rec.isLastRule = true; - } else if ("only".equals(token)) { + } else if (token.regionMatches(true, 0, "only", 0, len)) { rec.toYear = rec.fromYear; } else { Main.panic("invalid year value: "+token); diff --git a/test/jdk/sun/util/calendar/zi/Zoneinfo.java b/test/jdk/sun/util/calendar/zi/Zoneinfo.java index 6b21bfb5c05..a68aa7826b0 100644 --- a/test/jdk/sun/util/calendar/zi/Zoneinfo.java +++ b/test/jdk/sun/util/calendar/zi/Zoneinfo.java @@ -240,8 +240,9 @@ static Zoneinfo parse(String fname) { continue; } String token = tokens.nextToken(); + int len = token.length(); - if (continued || "Zone".equals(token)) { + if (continued || token.regionMatches(true, 0, "Zone", 0, len)){ if (zone == null) { if (!tokens.hasMoreTokens()) { panic("syntax error: zone no more token"); @@ -268,7 +269,7 @@ static Zoneinfo parse(String fname) { } zone = null; } - } else if ("Rule".equals(token)) { + } else if (token.regionMatches(true, 0, "Rule", 0, len)) { if (!tokens.hasMoreTokens()) { panic("syntax error: rule no more token"); } @@ -281,7 +282,7 @@ static Zoneinfo parse(String fname) { RuleRec rrec = RuleRec.parse(tokens); rrec.setLine(line); rule.add(rrec); - } else if ("Link".equals(token)) { + } else if (token.regionMatches(true, 0, "Link", 0, len)) { // Link try { String name1 = tokens.nextToken();