From aa98d5d20b33cfed2bf62db263fcb2cb8b36a81c Mon Sep 17 00:00:00 2001 From: Phil Race Date: Thu, 4 Jun 2026 19:09:19 +0000 Subject: [PATCH 1/7] 8385100: Null pointer dereference in java.desktop/windows/classes/sun/print/Win32PrintJob.java:606 and other PrintJob implementations Reviewed-by: psadhukhan, kizune --- .../classes/sun/print/PSStreamPrintJob.java | 4 +- .../unix/classes/sun/print/UnixPrintJob.java | 4 +- .../classes/sun/print/Win32PrintJob.java | 4 +- .../javax/print/NullUserNamePrintingTest.java | 58 ++++++++++++++ .../print/NullUserNameStreamPrintingTest.java | 75 +++++++++++++++++++ 5 files changed, 139 insertions(+), 6 deletions(-) create mode 100644 test/jdk/javax/print/NullUserNamePrintingTest.java create mode 100644 test/jdk/javax/print/NullUserNameStreamPrintingTest.java diff --git a/src/java.desktop/share/classes/sun/print/PSStreamPrintJob.java b/src/java.desktop/share/classes/sun/print/PSStreamPrintJob.java index dcafdb86460..0f420186f60 100644 --- a/src/java.desktop/share/classes/sun/print/PSStreamPrintJob.java +++ b/src/java.desktop/share/classes/sun/print/PSStreamPrintJob.java @@ -436,8 +436,8 @@ public class PSStreamPrintJob implements CancelablePrintJob { /* add the user name to the job */ String userName = System.getProperty("user.name"); if (userName == null || userName.isEmpty()) { - RequestingUserName ruName = - (RequestingUserName)reqSet.get(RequestingUserName.class); + RequestingUserName ruName = (reqSet != null) ? + (RequestingUserName)reqSet.get(RequestingUserName.class) : null; if (ruName != null) { jobAttrSet.add( new JobOriginatingUserName(ruName.getValue(), diff --git a/src/java.desktop/unix/classes/sun/print/UnixPrintJob.java b/src/java.desktop/unix/classes/sun/print/UnixPrintJob.java index 4604167a0e4..c75efac714a 100644 --- a/src/java.desktop/unix/classes/sun/print/UnixPrintJob.java +++ b/src/java.desktop/unix/classes/sun/print/UnixPrintJob.java @@ -716,8 +716,8 @@ public final class UnixPrintJob implements CancelablePrintJob { /* add the user name to the job */ String userName = System.getProperty("user.name"); if (userName == null || userName.isEmpty()) { - RequestingUserName ruName = - (RequestingUserName)reqSet.get(RequestingUserName.class); + RequestingUserName ruName = (reqSet != null) ? + (RequestingUserName)reqSet.get(RequestingUserName.class) : null; if (ruName != null) { jobAttrSet.add( new JobOriginatingUserName(ruName.getValue(), diff --git a/src/java.desktop/windows/classes/sun/print/Win32PrintJob.java b/src/java.desktop/windows/classes/sun/print/Win32PrintJob.java index 0afd0ed60c7..48cf1472016 100644 --- a/src/java.desktop/windows/classes/sun/print/Win32PrintJob.java +++ b/src/java.desktop/windows/classes/sun/print/Win32PrintJob.java @@ -602,8 +602,8 @@ public final class Win32PrintJob implements CancelablePrintJob { String userName = System.getProperty("user.name"); if (userName == null || userName.isEmpty()) { - RequestingUserName ruName = - (RequestingUserName)reqSet.get(RequestingUserName.class); + RequestingUserName ruName = (reqSet != null) ? + (RequestingUserName)reqSet.get(RequestingUserName.class) : null; if (ruName != null) { jobAttrSet.add( new JobOriginatingUserName(ruName.getValue(), diff --git a/test/jdk/javax/print/NullUserNamePrintingTest.java b/test/jdk/javax/print/NullUserNamePrintingTest.java new file mode 100644 index 00000000000..5051959447b --- /dev/null +++ b/test/jdk/javax/print/NullUserNamePrintingTest.java @@ -0,0 +1,58 @@ +/* + * 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. + */ + +/* + * @test + * @bug 8385100 + * @key printer + * @summary Should not get NPE if atttribute set is null. + */ + +import java.io.ByteArrayInputStream; +import javax.print.Doc; +import javax.print.DocFlavor; +import javax.print.DocPrintJob; +import javax.print.PrintException; +import javax.print.PrintService; +import javax.print.PrintServiceLookup; +import javax.print.SimpleDoc; + +public class NullUserNamePrintingTest { + + public static void main(String[] args) throws PrintException { + PrintService[] services = PrintServiceLookup.lookupPrintServices(null, null); + if (services.length == 0) { + System.err.println("This test requires a printer."); + return; + } + PrintService service = services[0]; + + DocPrintJob job = service.createPrintJob(); + + Doc doc = new SimpleDoc( + new ByteArrayInputStream("Test print".getBytes()), + DocFlavor.INPUT_STREAM.AUTOSENSE, null); + System.setProperty("user.name", ""); + job.print(doc, null); + } +} diff --git a/test/jdk/javax/print/NullUserNameStreamPrintingTest.java b/test/jdk/javax/print/NullUserNameStreamPrintingTest.java new file mode 100644 index 00000000000..475b8acbfd7 --- /dev/null +++ b/test/jdk/javax/print/NullUserNameStreamPrintingTest.java @@ -0,0 +1,75 @@ +/* + * 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. + */ + +/* + * @test + * @bug 8385100 + * @summary Should not get NPE if atttribute set is null. + */ + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.awt.Graphics; +import java.awt.print.PageFormat; +import java.awt.print.Printable; +import java.awt.print.PrinterException; +import javax.print.Doc; +import javax.print.DocFlavor; +import javax.print.DocPrintJob; +import javax.print.PrintException; +import javax.print.PrintService; +import javax.print.PrintServiceLookup; +import javax.print.SimpleDoc; +import javax.print.StreamPrintService; +import javax.print.StreamPrintServiceFactory; + +public class NullUserNameStreamPrintingTest implements Printable { + + public static void main(String[] args) throws PrintException { + + DocFlavor flavor = DocFlavor.SERVICE_FORMATTED.PRINTABLE; + String mime = "application/postscript"; + StreamPrintServiceFactory[] factories = + StreamPrintServiceFactory.lookupStreamPrintServiceFactories(flavor, mime); + if (factories.length == 0) { + throw new RuntimeException("Unable to find PostScript print service factory"); + } + StreamPrintServiceFactory factory = factories[0]; + ByteArrayOutputStream output = new ByteArrayOutputStream(); + StreamPrintService service = factory.getPrintService(output); + + DocPrintJob job = service.createPrintJob(); + + Doc doc = new SimpleDoc(new NullUserNameStreamPrintingTest(), flavor, null); + System.setProperty("user.name", ""); + job.print(doc, null); + } + + public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) + throws PrinterException { + if (pageIndex > 0) { + return NO_SUCH_PAGE; + } + return PAGE_EXISTS; + } +} From cf78a2a89a1a6d2efe4b0339f7ebec960eec0a53 Mon Sep 17 00:00:00 2001 From: Chad Rakoczy Date: Thu, 4 Jun 2026 19:36:30 +0000 Subject: [PATCH 2/7] 8384606: HotCodeHeap tests require C2 Reviewed-by: shade, kvn --- .../hotcode/HotCodeCollectorMoveFunction.java | 105 +++++++++++------- .../hotcode/StressHotCodeCollector.java | 5 +- 2 files changed, 70 insertions(+), 40 deletions(-) diff --git a/test/hotspot/jtreg/compiler/hotcode/HotCodeCollectorMoveFunction.java b/test/hotspot/jtreg/compiler/hotcode/HotCodeCollectorMoveFunction.java index dd02de66881..5677ca88eb2 100644 --- a/test/hotspot/jtreg/compiler/hotcode/HotCodeCollectorMoveFunction.java +++ b/test/hotspot/jtreg/compiler/hotcode/HotCodeCollectorMoveFunction.java @@ -24,14 +24,15 @@ /* * @test + * @summary Ensure the HotCodeCollector detects a very hot method and relocates + * it to the HotCodeHeap. Sampling is best effort, so for reliability + * we spawn a seperate test process to manage the VM flags. + * @requires vm.flagless + * @requires vm.compiler2.enabled * @library /test/lib / * @build jdk.test.whitebox.WhiteBox * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -Xbatch -XX:-TieredCompilation -XX:+SegmentedCodeCache -XX:+UnlockExperimentalVMOptions -XX:+HotCodeHeap - * -XX:+NMethodRelocation -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:HotCodeIntervalSeconds=0 -XX:HotCodeCallLevel=0 - * -XX:HotCodeSampleSeconds=5 -XX:HotCodeStablePercent=-1 -XX:HotCodeSamplePercent=100 -XX:HotCodeStartupDelaySeconds=0 - * -XX:CompileCommand=compileonly,compiler.hotcode.HotCodeCollectorMoveFunction::func - * compiler.hotcode.HotCodeCollectorMoveFunction + * @run driver compiler.hotcode.HotCodeCollectorMoveFunction */ package compiler.hotcode; @@ -39,50 +40,78 @@ package compiler.hotcode; import java.lang.reflect.Method; import jdk.test.lib.Asserts; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; import jdk.test.whitebox.WhiteBox; import jdk.test.whitebox.code.BlobType; import jdk.test.whitebox.code.NMethod; public class HotCodeCollectorMoveFunction { - private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); - private static final Method method; - private static final int C2_LEVEL = 4; - private static final int FUNC_RUN_MILLIS = 60_000; - - static { - try { - method = HotCodeCollectorMoveFunction.class.getMethod("func"); - } catch (NoSuchMethodException e) { - throw new RuntimeException(e); - } - } - public static void main(String[] args) throws Exception { - WHITE_BOX.testSetDontInlineMethod(method, true); + ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( + "-Xbootclasspath/a:.", + "-Xbatch", + "-XX:-TieredCompilation", + "-XX:+SegmentedCodeCache", + "-XX:+UnlockExperimentalVMOptions", + "-XX:+HotCodeHeap", + "-XX:+NMethodRelocation", + "-XX:+UnlockDiagnosticVMOptions", + "-XX:+WhiteBoxAPI", + "-XX:HotCodeIntervalSeconds=0", + "-XX:HotCodeCallLevel=0", + "-XX:HotCodeSampleSeconds=5", + "-XX:HotCodeStablePercent=-1", + "-XX:HotCodeSamplePercent=100", + "-XX:HotCodeStartupDelaySeconds=0", + "-XX:CompileCommand=compileonly," + Runner.class.getName() + "::func", + Runner.class.getName() + ); - compileFunc(); - - // Call function so collector samples and relocates - func(); - - // Function should now be in the Hot code heap after collector has had time to relocate - NMethod reloc_nm = NMethod.get(method, false); - Asserts.assertNotEquals(reloc_nm, null); - Asserts.assertEQ(reloc_nm.code_blob_type, BlobType.MethodHot); + OutputAnalyzer out = new OutputAnalyzer(pb.start()); + out.shouldHaveExitValue(0); } - public static void compileFunc() { - WHITE_BOX.enqueueMethodForCompilation(method, C2_LEVEL); + static class Runner { + private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); + private static final Method method; + private static final int C2_LEVEL = 4; + private static final int FUNC_RUN_MILLIS = 60_000; - if (WHITE_BOX.getMethodCompilationLevel(method) != C2_LEVEL) { - throw new IllegalStateException("Method " + method + " is not compiled by C2."); + static { + try { + method = Runner.class.getMethod("func"); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } + } + + public static void main(String[] args) { + WHITE_BOX.testSetDontInlineMethod(method, true); + + compileFunc(); + + // Call function so collector samples and relocates + func(); + + // Function should now be in the Hot code heap after collector has had time to relocate + NMethod relocatedNMethod = NMethod.get(method, false); + Asserts.assertNotNull(relocatedNMethod); + Asserts.assertEQ(BlobType.MethodHot, relocatedNMethod.code_blob_type); + } + + private static void compileFunc() { + WHITE_BOX.enqueueMethodForCompilation(method, C2_LEVEL); + + if (WHITE_BOX.getMethodCompilationLevel(method) != C2_LEVEL) { + throw new IllegalStateException("Method " + method + " is not compiled by C2."); + } + } + + public static void func() { + long start = System.currentTimeMillis(); + while (System.currentTimeMillis() - start < FUNC_RUN_MILLIS) {} } } - - public static void func() { - long start = System.currentTimeMillis(); - while (System.currentTimeMillis() - start < FUNC_RUN_MILLIS) {} - } - } diff --git a/test/hotspot/jtreg/compiler/hotcode/StressHotCodeCollector.java b/test/hotspot/jtreg/compiler/hotcode/StressHotCodeCollector.java index b107df8fa46..551b9ea2fca 100644 --- a/test/hotspot/jtreg/compiler/hotcode/StressHotCodeCollector.java +++ b/test/hotspot/jtreg/compiler/hotcode/StressHotCodeCollector.java @@ -26,11 +26,12 @@ /* * @test * @key randomness + * @requires vm.compiler2.enabled & vm.opt.SegmentedCodeCache != false * @library /test/lib / * @build jdk.test.whitebox.WhiteBox * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -Xcomp -XX:-TieredCompilation -XX:+UnlockExperimentalVMOptions -XX:+HotCodeHeap -XX:+NMethodRelocation - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:HotCodeIntervalSeconds=0 -XX:HotCodeSampleSeconds=10 + * @run main/othervm -Xbootclasspath/a:. -Xcomp -XX:-TieredCompilation -XX:+SegmentedCodeCache -XX:+UnlockExperimentalVMOptions -XX:+HotCodeHeap + * -XX:+NMethodRelocation -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:HotCodeIntervalSeconds=0 -XX:HotCodeSampleSeconds=10 * -XX:HotCodeStablePercent=-1 -XX:HotCodeSamplePercent=100 -XX:HotCodeStartupDelaySeconds=0 * compiler.hotcode.StressHotCodeCollector */ From 5415a27ed8f3e8e6f40fa704f0aaf051965ec51a Mon Sep 17 00:00:00 2001 From: Chen Liang Date: Thu, 4 Jun 2026 20:43:30 +0000 Subject: [PATCH 3/7] 8385974: Update symbol information for jdk-28+0 Reviewed-by: darcy --- .../share/data/symbols/java.base-R.sym.txt | 86 ++++++++++++++++++- .../share/data/symbols/java.desktop-R.sym.txt | 4 + .../symbols/jdk.incubator.foreign-R.sym.txt | 4 + 3 files changed, 92 insertions(+), 2 deletions(-) diff --git a/src/jdk.compiler/share/data/symbols/java.base-R.sym.txt b/src/jdk.compiler/share/data/symbols/java.base-R.sym.txt index 85ec80d9f8e..9853f8c70fd 100644 --- a/src/jdk.compiler/share/data/symbols/java.base-R.sym.txt +++ b/src/jdk.compiler/share/data/symbols/java.base-R.sym.txt @@ -120,12 +120,75 @@ method name parameterModifiers descriptor ()I flags 9 deprecated true runtimeAnn class name java/math/BigDecimal method name rootn descriptor (ILjava/math/MathContext;)Ljava/math/BigDecimal; flags 1 +class name java/security/AsymmetricKey +header extends java/lang/Object implements java/security/Key,java/security/BinaryEncodable flags 601 + +class name java/security/BinaryEncodable +header extends java/lang/Object sealed true permittedSubclasses java/security/AsymmetricKey,java/security/KeyPair,java/security/spec/PKCS8EncodedKeySpec,java/security/spec/X509EncodedKeySpec,javax/crypto/EncryptedPrivateKeyInfo,java/security/cert/X509Certificate,java/security/cert/X509CRL,java/security/PEM flags 601 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;PEM_API;) + +-class name java/security/DEREncodable + +class name java/security/KeyPair +header extends java/lang/Object implements java/io/Serializable,java/security/BinaryEncodable flags 31 + class name java/security/KeyStore method name getCreationInstant descriptor (Ljava/lang/String;)Ljava/time/Instant; thrownTypes java/security/KeyStoreException flags 11 class name java/security/KeyStoreSpi method name engineGetCreationInstant descriptor (Ljava/lang/String;)Ljava/time/Instant; flags 1 +class name java/security/PEM +header extends java/lang/Object implements java/security/BinaryEncodable flags 31 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;PEM_API;) +innerclass innerClass java/lang/ref/Cleaner$Cleanable outerClass java/lang/ref/Cleaner innerClassName Cleanable flags 609 +innerclass innerClass java/util/Base64$Decoder outerClass java/util/Base64 innerClassName Decoder flags 9 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 +-method name toString descriptor ()Ljava/lang/String; +-method name decode descriptor ()[B +-method name hashCode descriptor ()I +-method name equals descriptor (Ljava/lang/Object;)Z +-method name content descriptor ()Ljava/lang/String; +method name descriptor (Ljava/lang/String;[B[B)V flags 1 +method name descriptor (Ljava/lang/String;[B)V flags 1 +method name content descriptor ()[B flags 1 +method name decode descriptor ()[B flags 1 +method name toString descriptor ()Ljava/lang/String; flags 1 + +class name java/security/PEMDecoder +header extends java/lang/Object flags 31 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;PEM_API;) +innerclass innerClass java/lang/ref/Cleaner$Cleanable outerClass java/lang/ref/Cleaner innerClassName Cleanable flags 609 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 +-method name decode descriptor (Ljava/lang/String;)Ljava/security/DEREncodable; +-method name decode descriptor (Ljava/io/InputStream;)Ljava/security/DEREncodable; +-method name decode descriptor (Ljava/lang/String;Ljava/lang/Class;)Ljava/security/DEREncodable; +-method name decode descriptor (Ljava/io/InputStream;Ljava/lang/Class;)Ljava/security/DEREncodable; +-method name withFactory descriptor (Ljava/security/Provider;)Ljava/security/PEMDecoder; +method name decode descriptor (Ljava/lang/String;)Ljava/security/BinaryEncodable; flags 1 +method name decode descriptor (Ljava/io/InputStream;)Ljava/security/BinaryEncodable; thrownTypes java/io/IOException flags 1 +method name decode descriptor (Ljava/lang/String;Ljava/lang/Class;)Ljava/security/BinaryEncodable; flags 1 signature (Ljava/lang/String;Ljava/lang/Class;)TS; +method name decode descriptor (Ljava/io/InputStream;Ljava/lang/Class;)Ljava/security/BinaryEncodable; thrownTypes java/io/IOException flags 1 signature (Ljava/io/InputStream;Ljava/lang/Class;)TS; +method name withFactoriesOf descriptor (Ljava/security/Provider;)Ljava/security/PEMDecoder; flags 1 + +class name java/security/PEMEncoder +header extends java/lang/Object flags 31 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;PEM_API;) +innerclass innerClass java/lang/ref/Cleaner$Cleanable outerClass java/lang/ref/Cleaner innerClassName Cleanable flags 609 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 +-method name encodeToString descriptor (Ljava/security/DEREncodable;)Ljava/lang/String; +-method name encode descriptor (Ljava/security/DEREncodable;)[B +method name encodeToString descriptor (Ljava/security/BinaryEncodable;)Ljava/lang/String; flags 1 +method name encode descriptor (Ljava/security/BinaryEncodable;)[B flags 1 + +class name java/security/cert/X509CRL +header extends java/security/cert/CRL implements java/security/cert/X509Extension,java/security/BinaryEncodable flags 421 + +class name java/security/cert/X509Certificate +header extends java/security/cert/Certificate implements java/security/cert/X509Extension,java/security/BinaryEncodable flags 421 + +class name java/security/spec/PKCS8EncodedKeySpec +header extends java/security/spec/EncodedKeySpec implements java/security/BinaryEncodable flags 21 + +class name java/security/spec/X509EncodedKeySpec +header extends java/security/spec/EncodedKeySpec implements java/security/BinaryEncodable flags 21 + class name java/text/AttributedString header extends java/lang/Object flags 21 innerclass innerClass java/text/AttributedCharacterIterator$Attribute outerClass java/text/AttributedCharacterIterator innerClassName Attribute flags 9 @@ -236,6 +299,27 @@ class name java/util/jar/Attributes$Name header extends java/lang/Object nestHost java/util/jar/Attributes flags 21 runtimeAnnotations @Ljdk/internal/vm/annotation/AOTSafeClassInitializer; innerclass innerClass java/util/jar/Attributes$Name outerClass java/util/jar/Attributes innerClassName Name flags 9 +class name javax/crypto/CryptoException +header extends java/lang/RuntimeException flags 31 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;PEM_API;) +method name descriptor ()V flags 1 +method name descriptor (Ljava/lang/String;)V flags 1 +method name descriptor (Ljava/lang/String;Ljava/lang/Throwable;)V flags 1 +method name descriptor (Ljava/lang/Throwable;)V flags 1 + +class name javax/crypto/EncryptedPrivateKeyInfo +header extends java/lang/Object implements java/security/BinaryEncodable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 +-method name encrypt descriptor (Ljava/security/DEREncodable;[CLjava/lang/String;Ljava/security/spec/AlgorithmParameterSpec;Ljava/security/Provider;)Ljavax/crypto/EncryptedPrivateKeyInfo; +-method name encrypt descriptor (Ljava/security/DEREncodable;[C)Ljavax/crypto/EncryptedPrivateKeyInfo; +-method name encrypt descriptor (Ljava/security/DEREncodable;Ljava/security/Key;Ljava/lang/String;Ljava/security/spec/AlgorithmParameterSpec;Ljava/security/Provider;Ljava/security/SecureRandom;)Ljavax/crypto/EncryptedPrivateKeyInfo; +-method name getKey descriptor (Ljava/security/Key;Ljava/security/Provider;)Ljava/security/PrivateKey; +-method name getKeyPair descriptor (Ljava/security/Key;Ljava/security/Provider;)Ljava/security/KeyPair; +method name encrypt descriptor (Ljava/security/BinaryEncodable;[CLjava/lang/String;Ljava/security/spec/AlgorithmParameterSpec;Ljava/security/Provider;)Ljavax/crypto/EncryptedPrivateKeyInfo; flags 9 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;PEM_API;) +method name encrypt descriptor (Ljava/security/BinaryEncodable;[C)Ljavax/crypto/EncryptedPrivateKeyInfo; flags 9 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;PEM_API;) +method name encrypt descriptor (Ljava/security/BinaryEncodable;Ljava/security/Key;Ljava/lang/String;Ljava/security/spec/AlgorithmParameterSpec;Ljava/security/Provider;Ljava/security/SecureRandom;)Ljavax/crypto/EncryptedPrivateKeyInfo; flags 9 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;PEM_API;) +method name getKey descriptor (Ljava/security/Key;)Ljava/security/PrivateKey; thrownTypes java/security/NoSuchAlgorithmException,java/security/InvalidKeyException flags 1 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;PEM_API;) +method name getKeyPair descriptor (Ljava/security/Key;)Ljava/security/KeyPair; thrownTypes java/security/NoSuchAlgorithmException,java/security/InvalidKeyException flags 1 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;PEM_API;) + class name jdk/internal/classfile/impl/AbstractInstruction$UnboundIncrementInstruction -method name descriptor (II)V method name descriptor (Ljava/lang/classfile/Opcode;II)V flags 1 @@ -328,8 +412,6 @@ innerclass innerClass jdk/internal/foreign/layout/ValueLayouts$OfShortImpl outer innerclass innerClass java/lang/foreign/ValueLayout$OfShort outerClass java/lang/foreign/ValueLayout innerClassName OfShort flags 609 class name jdk/internal/lang/LazyConstantImpl -header extends java/lang/Object implements java/lang/LazyConstant flags 31 signature Ljava/lang/Object;Ljava/lang/LazyConstant; runtimeAnnotations @Ljdk/internal/vm/annotation/AOTSafeClassInitializer; -innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 -method name isInitialized descriptor ()Z method name isolateToString descriptor (Ljava/lang/Object;)Ljava/lang/String; flags 9 diff --git a/src/jdk.compiler/share/data/symbols/java.desktop-R.sym.txt b/src/jdk.compiler/share/data/symbols/java.desktop-R.sym.txt index 19f7a3a8317..41ce8137405 100644 --- a/src/jdk.compiler/share/data/symbols/java.desktop-R.sym.txt +++ b/src/jdk.compiler/share/data/symbols/java.desktop-R.sym.txt @@ -36,6 +36,10 @@ method name getBounds descriptor ()Ljava/awt/Rectangle; flags 1 class name java/awt/image/DataBufferUShort header extends java/awt/image/DataBuffer flags 31 classAnnotations @Ljdk/Profile+Annotation;(value=I4) +class name java/awt/image/PixelInterleavedSampleModel +header extends java/awt/image/ComponentSampleModel flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + class name javax/swing/JEditorPane$AccessibleJEditorPaneHTML header extends javax/swing/JEditorPane$AccessibleJEditorPane nestHost javax/swing/JEditorPane flags 21 innerclass innerClass javax/swing/JEditorPane$AccessibleJEditorPaneHTML outerClass javax/swing/JEditorPane innerClassName AccessibleJEditorPaneHTML flags 4 diff --git a/src/jdk.compiler/share/data/symbols/jdk.incubator.foreign-R.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.incubator.foreign-R.sym.txt index f0c763f92e0..2e193e68188 100644 --- a/src/jdk.compiler/share/data/symbols/jdk.incubator.foreign-R.sym.txt +++ b/src/jdk.compiler/share/data/symbols/jdk.incubator.foreign-R.sym.txt @@ -30,6 +30,10 @@ class name jdk/internal/foreign/AbstractMemorySegmentImpl method name getString descriptor (JLjava/nio/charset/Charset;J)Ljava/lang/String; flags 1 runtimeAnnotations @Ljdk/internal/vm/annotation/ForceInline; method name copy descriptor (Ljava/lang/String;Ljava/nio/charset/Charset;ILjava/lang/foreign/MemorySegment;JI)J flags 9 runtimeAnnotations @Ljdk/internal/vm/annotation/ForceInline; +class name jdk/internal/foreign/FunctionDescriptorImpl +header extends java/lang/Object implements java/lang/foreign/FunctionDescriptor flags 31 runtimeAnnotations @Ljdk/internal/ValueBased; +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + class name jdk/internal/foreign/HeapMemorySegmentImpl$OfByte header extends jdk/internal/foreign/HeapMemorySegmentImpl nestHost jdk/internal/foreign/HeapMemorySegmentImpl flags 31 runtimeAnnotations @Ljdk/internal/ValueBased; innerclass innerClass jdk/internal/foreign/HeapMemorySegmentImpl$OfByte outerClass jdk/internal/foreign/HeapMemorySegmentImpl innerClassName OfByte flags 19 From 55d528eb377795983f68089f83fb6c67840933f9 Mon Sep 17 00:00:00 2001 From: Archie Cobbs Date: Thu, 4 Jun 2026 23:07:47 +0000 Subject: [PATCH 4/7] 8385660: Audit and remove unnecessary lint categories from $DISABLED_WARNINGS Reviewed-by: erikj, asemenyuk, prr --- make/CompileDemos.gmk | 18 +++++++++--------- make/modules/jdk.internal.le/Java.gmk | 4 +--- make/modules/jdk.jpackage/Java.gmk | 2 -- make/test/BuildMicrobenchmark.gmk | 6 +++--- make/test/BuildTestLib.gmk | 3 +-- 5 files changed, 14 insertions(+), 19 deletions(-) diff --git a/make/CompileDemos.gmk b/make/CompileDemos.gmk index 503edf18e00..ab3545facec 100644 --- a/make/CompileDemos.gmk +++ b/make/CompileDemos.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 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 @@ -173,41 +173,41 @@ $(BUILD_DEMO_CodePointIM_JAR): $(CODEPOINT_METAINF_SERVICE_FILE) $(eval $(call SetupBuildDemo, FileChooserDemo, \ DEMO_SUBDIR := jfc, \ - DISABLED_WARNINGS := rawtypes deprecation unchecked this-escape, \ + DISABLED_WARNINGS := this-escape, \ )) $(eval $(call SetupBuildDemo, SwingSet2, \ DEMO_SUBDIR := jfc, \ EXTRA_COPY_TO_JAR := .java, \ EXTRA_MANIFEST_ATTR := SplashScreen-Image: resources/images/splash.png, \ - DISABLED_WARNINGS := rawtypes deprecation unchecked static serial cast this-escape, \ + DISABLED_WARNINGS := rawtypes static serial cast this-escape, \ )) $(eval $(call SetupBuildDemo, Font2DTest, \ - DISABLED_WARNINGS := rawtypes deprecation unchecked serial cast this-escape dangling-doc-comments, \ + DISABLED_WARNINGS := serial dangling-doc-comments, \ DEMO_SUBDIR := jfc, \ )) $(eval $(call SetupBuildDemo, J2Ddemo, \ DEMO_SUBDIR := jfc, \ MAIN_CLASS := java2d.J2Ddemo, \ - DISABLED_WARNINGS := rawtypes deprecation unchecked cast lossy-conversions this-escape, \ + DISABLED_WARNINGS := cast lossy-conversions this-escape, \ JAR_NAME := J2Ddemo, \ )) $(eval $(call SetupBuildDemo, Metalworks, \ - DISABLED_WARNINGS := rawtypes unchecked this-escape, \ + DISABLED_WARNINGS := this-escape, \ DEMO_SUBDIR := jfc, \ )) $(eval $(call SetupBuildDemo, Notepad, \ - DISABLED_WARNINGS := rawtypes this-escape, \ + DISABLED_WARNINGS := this-escape, \ DEMO_SUBDIR := jfc, \ )) $(eval $(call SetupBuildDemo, Stylepad, \ DEMO_SUBDIR := jfc, \ - DISABLED_WARNINGS := rawtypes unchecked this-escape, \ + DISABLED_WARNINGS := this-escape, \ EXTRA_SRC_DIR := $(DEMO_SHARE_SRC)/jfc/Notepad, \ EXCLUDE_FILES := $(DEMO_SHARE_SRC)/jfc/Notepad/README.txt, \ )) @@ -217,7 +217,7 @@ $(eval $(call SetupBuildDemo, SampleTree, \ )) $(eval $(call SetupBuildDemo, TableExample, \ - DISABLED_WARNINGS := rawtypes unchecked deprecation this-escape dangling-doc-comments, \ + DISABLED_WARNINGS := dangling-doc-comments, \ DEMO_SUBDIR := jfc, \ )) diff --git a/make/modules/jdk.internal.le/Java.gmk b/make/modules/jdk.internal.le/Java.gmk index 27c6eaf5f7f..d101f582484 100644 --- a/make/modules/jdk.internal.le/Java.gmk +++ b/make/modules/jdk.internal.le/Java.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2020, 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 @@ -25,8 +25,6 @@ ################################################################################ -DISABLED_WARNINGS_java += dangling-doc-comments this-escape - COPY += .properties .caps .txt ################################################################################ diff --git a/make/modules/jdk.jpackage/Java.gmk b/make/modules/jdk.jpackage/Java.gmk index 1fd4d527217..f36c83d772e 100644 --- a/make/modules/jdk.jpackage/Java.gmk +++ b/make/modules/jdk.jpackage/Java.gmk @@ -25,8 +25,6 @@ ################################################################################ -DISABLED_WARNINGS_java += dangling-doc-comments - COPY += .gif .png .txt .spec .script .prerm .preinst \ .postrm .postinst .list .sh .desktop .copyright .control .plist .template \ .icns .scpt .wxs .wxl .wxi .wxf .ico .bmp .tiff .service .xsl .js diff --git a/make/test/BuildMicrobenchmark.gmk b/make/test/BuildMicrobenchmark.gmk index 4946263ef4e..c71ef7c61af 100644 --- a/make/test/BuildMicrobenchmark.gmk +++ b/make/test/BuildMicrobenchmark.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2018, 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 @@ -83,8 +83,8 @@ $(eval $(call SetupJavaCompilation, BUILD_JDK_MICROBENCHMARK, \ SMALL_JAVA := false, \ CLASSPATH := $(JMH_COMPILE_JARS), \ CREATE_API_DIGEST := true, \ - DISABLED_WARNINGS := restricted this-escape processing rawtypes removal cast \ - serial preview dangling-doc-comments, \ + DISABLED_WARNINGS := restricted this-escape rawtypes removal cast \ + serial preview, \ SRC := $(MICROBENCHMARK_SRC), \ BIN := $(MICROBENCHMARK_CLASSES), \ JAVAC_FLAGS := \ diff --git a/make/test/BuildTestLib.gmk b/make/test/BuildTestLib.gmk index dc5e0a9bd64..3668a918ab1 100644 --- a/make/test/BuildTestLib.gmk +++ b/make/test/BuildTestLib.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2015, 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 @@ -46,7 +46,6 @@ $(eval $(call SetupJavaCompilation, BUILD_WB_JAR, \ SRC := $(TEST_LIB_SOURCE_DIR)/jdk/test/whitebox/, \ BIN := $(TEST_LIB_SUPPORT)/wb_classes, \ JAR := $(TEST_LIB_SUPPORT)/wb.jar, \ - DISABLED_WARNINGS := deprecation removal preview, \ JAVAC_FLAGS := --enable-preview, \ )) From 92298786486daf092c8eb8f278818441df1f6b51 Mon Sep 17 00:00:00 2001 From: Xueming Shen Date: Fri, 5 Jun 2026 00:10:44 +0000 Subject: [PATCH 5/7] 8385355: NullPointerException in jdk.tools.jlink.internal.ImageResourcesTree after JDK-8377070 Co-authored-by: David Beaumont Reviewed-by: alanb --- .../jlink/internal/ImageResourcesTree.java | 40 +++++++++++++++---- .../jdk/internal/jimage/ImageReaderTest.java | 32 ++++++++++++++- 2 files changed, 62 insertions(+), 10 deletions(-) diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageResourcesTree.java b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageResourcesTree.java index 2f8143820ca..ab0809348ca 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageResourcesTree.java +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageResourcesTree.java @@ -235,22 +235,46 @@ public final class ImageResourcesTree { return; } String modName = fullPath.substring(1, modEnd); - String pkgPath = fullPath.substring(modEnd + 1); + String resPath = fullPath.substring(modEnd + 1); + int pathEnd = resPath.lastIndexOf('/'); Node parentNode = getDirectoryNode(modName, modulesRoot); boolean isPreviewPath = false; - if (pkgPath.startsWith(PREVIEW_PREFIX)) { + if (resPath.startsWith("META-INF/")) { + parentNode = getDirectoryNode("META-INF", parentNode); + if (!resPath.startsWith(PREVIEW_PREFIX)) { + // Non-preview META-INF paths are resources, not package + // hierarchies, so directory and file names may contain dots. + for (int i = "META-INF".length(), j; i != pathEnd; i = j) { + j = resPath.indexOf('/', i + 1); + parentNode = getDirectoryNode(resPath.substring(i + 1, j), parentNode); + } + String resourceName = resPath.substring(pathEnd + 1); + Node resourceNode = parentNode.getChildren(resourceName); + if (resourceNode == null) { + new ResourceNode(resourceName, parentNode); + } else if (!(resourceNode instanceof ResourceNode)) { + throw new InvalidTreeException(resourceNode); + } + return; + } // For preview paths, process nodes relative to the preview directory. - pkgPath = pkgPath.substring(PREVIEW_PREFIX.length()); - Node metaInf = getDirectoryNode("META-INF", parentNode); - parentNode = getDirectoryNode("preview", metaInf); + parentNode = getDirectoryNode("preview", parentNode); + resPath = resPath.substring(PREVIEW_PREFIX.length()); + pathEnd -= PREVIEW_PREFIX.length(); isPreviewPath = true; } - int pathEnd = pkgPath.lastIndexOf('/'); // From invariants tested above, this must now be well-formed. - String fullPkgName = (pathEnd == -1) ? "" : pkgPath.substring(0, pathEnd).replace('/', '.'); - String resourceName = pkgPath.substring(pathEnd + 1); + String pkgPath = (pathEnd == -1) ? "" : resPath.substring(0, pathEnd); + if (pkgPath.contains(".")) { + // Non META-INF entries are package paths. Dots in path segment + // names would otherwise be confused with package separators. + System.err.println("Invalid package path, skipping " + pkgPath); + return; + } + String fullPkgName = pkgPath.replace('/', '.'); + String resourceName = resPath.substring(pathEnd + 1); // Intermediate packages are marked "empty" (no resources). This might // later be merged with a non-empty link for the same package. ModuleLink emptyLink = ModuleLink.forEmptyPackage(modName, isPreviewPath); diff --git a/test/jdk/jdk/internal/jimage/ImageReaderTest.java b/test/jdk/jdk/internal/jimage/ImageReaderTest.java index b8f7763e97e..5104bb97f95 100644 --- a/test/jdk/jdk/internal/jimage/ImageReaderTest.java +++ b/test/jdk/jdk/internal/jimage/ImageReaderTest.java @@ -37,6 +37,7 @@ import tests.Helper; import tests.JImageGenerator; import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.util.Arrays; import java.util.List; @@ -58,6 +59,7 @@ import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; /* * @test + * @bug 8385355 * @summary Tests for ImageReader. * @modules java.base/jdk.internal.jimage * jdk.jlink/jdk.tools.jlink.internal @@ -72,13 +74,18 @@ import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; /// There is no mutable test instance state to worry about. @TestInstance(PER_CLASS) public class ImageReaderTest { - // The '@' prefix marks the entry as a preview entry which will be placed in - // the '/modules//META-INF/preview/...' namespace. + // The '@' prefix marks the entry as a preview class entry which will be placed in + // the '/modules//META-INF/preview/...' namespace. The '!' prefix marks + // the entry as a non-class resource path. private static final Map> IMAGE_ENTRIES = Map.of( "modfoo", Arrays.asList( "com.foo.HasPreviewVersion", "com.foo.NormalFoo", "com.foo.bar.NormalBar", + "!META-INF/maven/com.google.code.findbugs/jsr305/pom.properties", + "!META-INF/z", + "!META-INF/collision/child.properties", + "!META-INF/collision", // Replaces original class in preview mode. "@com.foo.HasPreviewVersion", // New class in existing package in preview mode. @@ -138,6 +145,23 @@ public class ImageReaderTest { } } + @Test + public void testMetaInfResourcesAreNotPackagePaths() throws IOException { + for (PreviewMode mode : List.of(PreviewMode.ENABLED, PreviewMode.DISABLED)) { + try (ImageReader reader = ImageReader.open(image, mode)) { + assertResource(reader, "modfoo", "META-INF/maven/com.google.code.findbugs/jsr305/pom.properties"); + assertResource(reader, "modfoo", "META-INF/z"); + assertResource(reader, "modfoo", "META-INF/collision/child.properties"); + assertDirContents(reader, "/modules/modfoo/META-INF", "MANIFEST.MF", "collision", "maven", "z"); + assertDirContents(reader, "/modules/modfoo/META-INF/collision", "child.properties"); + assertDirContents(reader, "/modules/modfoo/META-INF/maven", "com.google.code.findbugs"); + assertDirContents(reader, "/modules/modfoo/META-INF/maven/com.google.code.findbugs", "jsr305"); + assertDirContents(reader, "/modules/modfoo/META-INF/maven/com.google.code.findbugs/jsr305", "pom.properties"); + assertAbsent(reader, "/modules/modfoo/META-INF/maven/com/google/code/findbugs/jsr305/pom.properties"); + } + } + } + @ParameterizedTest @CsvSource(delimiter = ':', value = { "modfoo:com/foo/HasPreviewVersion.class", @@ -416,6 +440,10 @@ public class ImageReaderTest { jar.addEntry("module-info.class", InMemoryJavaCompiler.compile("module-info", moduleInfo)); classes.forEach(fqn -> { + if (fqn.startsWith("!")) { + jar.addEntry(fqn.substring(1), "resource".getBytes(StandardCharsets.UTF_8)); + return; + } boolean isPreviewEntry = fqn.startsWith("@"); if (isPreviewEntry) { fqn = fqn.substring(1); From cc69221519470b0c95bdbde5914fc8f808ba0ffb Mon Sep 17 00:00:00 2001 From: Emanuel Peter Date: Fri, 5 Jun 2026 05:44:21 +0000 Subject: [PATCH 6/7] 8381618: VectorExpressionFuzzer.java: enable test for all platforms Reviewed-by: vlivanov, mhaessig --- .../vectorapi/VectorExpressionFuzzer.java | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/test/hotspot/jtreg/compiler/vectorapi/VectorExpressionFuzzer.java b/test/hotspot/jtreg/compiler/vectorapi/VectorExpressionFuzzer.java index 12615d839ab..cb5b95109f5 100644 --- a/test/hotspot/jtreg/compiler/vectorapi/VectorExpressionFuzzer.java +++ b/test/hotspot/jtreg/compiler/vectorapi/VectorExpressionFuzzer.java @@ -22,26 +22,17 @@ */ /* - * @test id=AVX2 - * @bug 8369699 + * @test + * @bug 8369699 8381618 * @key randomness * @summary Test the Template Library's expression generation for the Vector API. - * @requires os.family == "linux" & os.simpleArch == "x64" * @modules jdk.incubator.vector * @modules java.base/jdk.internal.misc * @library /test/lib / * @compile ../../compiler/lib/verify/Verify.java - * @run driver ${test.main.class} -XX:UseAVX=2 + * @run driver ${test.main.class} */ -// TODO: remove the x64 and linux restriction above. I added that for now so we are not flooded -// with failures in the CI. We should remove these restriction once more bugs are fixed. -// x64 linux is the easiest to debug on for me, that's why I picked it. -// In addition, I put a UseAVX=2 restriction below, to avoid AVX512 bugs for now. -// -// A trick to extend this to other platforms: create a new run block, so you have full -// freedom to restrict it as necessary for platform and vector features. -// // TODO: Some compilation bailouts are to be expected, for example, we've encountered this before: // COMPILE SKIPPED: out of virtual registers in LIR generator (retry at different tier) // Which manifested in: From 5719b671a226ac5cfd116e96d0c9b1c25607b41d Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Fri, 5 Jun 2026 07:33:51 +0000 Subject: [PATCH 7/7] 8385369: G1: Concurrent Cleanup For Next Mark accesses uncommitted bitmaps after region uncommit Reviewed-by: aboldtch, manc --- src/hotspot/share/gc/g1/g1ConcurrentMark.cpp | 15 +- .../share/gc/g1/g1UncommitRegionTask.cpp | 6 +- .../share/gc/g1/g1UncommitRegionTask.hpp | 4 +- src/hotspot/share/gc/g1/g1_globals.hpp | 6 +- ...stUncommitDuringConcurrentBitmapClear.java | 133 ++++++++++++++++++ 5 files changed, 154 insertions(+), 10 deletions(-) create mode 100644 test/hotspot/jtreg/resourcehogs/gc/TestUncommitDuringConcurrentBitmapClear.java diff --git a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp index 83dda2a043b..4afc7fa8ff1 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp @@ -714,6 +714,11 @@ private: } HeapWord* region_clear_limit(G1HeapRegion* r) { + // A garbage collection might have made the region unavailable after a yield during + // clearing. Just return bottom as the limit, causing the clearing for this region to end. + if (G1CollectedHeap::heap()->region_at_or_null(r->hrm_index()) == nullptr) { + return r->bottom(); + } // During a Concurrent Undo Mark cycle, the per region top_at_mark_start and // live_words data are current wrt to the _mark_bitmap. We use this information // to only clear ranges of the bitmap that require clearing. @@ -743,7 +748,7 @@ private: } HeapWord* cur = r->bottom(); - HeapWord* const end = region_clear_limit(r); + HeapWord* end = region_clear_limit(r); size_t const chunk_size_in_words = G1ClearBitMapTask::chunk_size() / HeapWordSize; @@ -761,8 +766,12 @@ private: assert(!suspendible() || _cm->is_in_reset_for_next_cycle(), "invariant"); // Abort iteration if necessary. - if (has_aborted()) { - return true; + if (suspendible() && _cm->do_yield_check()) { + if (_cm->has_aborted()) { + return true; + } + // Re-read end. The region might have been uncommitted. + end = region_clear_limit(r); } } assert(cur >= end, "Must have completed iteration over the bitmap for region %u.", r->hrm_index()); diff --git a/src/hotspot/share/gc/g1/g1UncommitRegionTask.cpp b/src/hotspot/share/gc/g1/g1UncommitRegionTask.cpp index e1203229557..f88736c5642 100644 --- a/src/hotspot/share/gc/g1/g1UncommitRegionTask.cpp +++ b/src/hotspot/share/gc/g1/g1UncommitRegionTask.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -58,9 +58,9 @@ void G1UncommitRegionTask::enqueue() { G1UncommitRegionTask* uncommit_task = instance(); if (!uncommit_task->is_active()) { - // Change state to active and schedule using UncommitInitialDelayMs. + // Change state to active and schedule. uncommit_task->set_active(true); - G1CollectedHeap::heap()->service_thread()->schedule_task(uncommit_task, UncommitInitialDelayMs); + G1CollectedHeap::heap()->service_thread()->schedule_task(uncommit_task, G1UncommitInitialDelay); } } diff --git a/src/hotspot/share/gc/g1/g1UncommitRegionTask.hpp b/src/hotspot/share/gc/g1/g1UncommitRegionTask.hpp index 7c9a25f6857..835217d2a59 100644 --- a/src/hotspot/share/gc/g1/g1UncommitRegionTask.hpp +++ b/src/hotspot/share/gc/g1/g1UncommitRegionTask.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -34,8 +34,6 @@ class G1UncommitRegionTask : public G1ServiceTask { // This limit is small enough to ensure that the duration of each invocation // is short, while still making reasonable progress. static const uint UncommitSizeLimit = 128 * M; - // Initial delay in milliseconds after GC before the regions are uncommitted. - static const uint UncommitInitialDelayMs = 100; // The delay between two uncommit task executions. static const uint UncommitTaskDelayMs = 10; diff --git a/src/hotspot/share/gc/g1/g1_globals.hpp b/src/hotspot/share/gc/g1/g1_globals.hpp index 14daac4800b..8a346c5c78f 100644 --- a/src/hotspot/share/gc/g1/g1_globals.hpp +++ b/src/hotspot/share/gc/g1/g1_globals.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -184,6 +184,10 @@ "shrink attempt.") \ range(0, 100) \ \ + develop(uint, G1UncommitInitialDelay, 100, \ + "Delay in milliseconds until regions just made eligible for " \ + "uncommit are actually uncommitted.") \ + \ product(uint, G1CPUUsageDeviationPercent, 25, DIAGNOSTIC, \ "The acceptable deviation (in percent) from the target GC CPU " \ "usage (based on GCTimeRatio). Creates a tolerance range " \ diff --git a/test/hotspot/jtreg/resourcehogs/gc/TestUncommitDuringConcurrentBitmapClear.java b/test/hotspot/jtreg/resourcehogs/gc/TestUncommitDuringConcurrentBitmapClear.java new file mode 100644 index 00000000000..f79f4992817 --- /dev/null +++ b/test/hotspot/jtreg/resourcehogs/gc/TestUncommitDuringConcurrentBitmapClear.java @@ -0,0 +1,133 @@ +/* + * 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. + */ + +package gc.g1; + +/* + * @test TestUncommitDuringConcurrentBitmapClear + * @bug 8385369 + * @requires vm.gc.G1 + * @requires vm.debug + * @requires vm.flagless + * @requires vm.bits == 64 + * @requires os.maxMemory > 8g + * @summary Verify that G1 does not crash while uncommitting a region whose + * bitmap is currently being cleared. + * Options are geared towards uncommitting aggressively. Also use a large + * region size so that corresponding bitmaps get uncommitted always too. + * @library /test/lib + * @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 + * -Xmx8g + * -Xms32m + * -XX:G1HeapRegionSize=16m + * -XX:+UseG1GC + * -XX:ConcGCThreads=1 + * -XX:GCTimeRatio=1 + * -XX:G1CPUUsageShrinkThreshold=1 + * -XX:G1ShrinkByPercentOfAvailable=100 + * -XX:G1UncommitInitialDelay=0 + * -Xlog:gc+marking,gc,gc+ergo+heap=debug + * gc.g1.TestUncommitDuringConcurrentBitmapClear + */ + +import java.util.concurrent.FutureTask; +import java.util.concurrent.TimeUnit; + +import jdk.test.whitebox.WhiteBox; + +/* + * Repeatedly make the concurrent cycle stop after the cleanup pause, issuing + * young GCs during the Concurrent Cleanup for Next Mark phase. Humongous + * regions allocated and dropped before that should get eager-reclaimed and + * their memory uncommitted while bitmap clearing runs. + */ +public class TestUncommitDuringConcurrentBitmapClear { + + private static final WhiteBox WB = WhiteBox.getWhiteBox(); + + private static final int NumObjs = 400; // Number of humongous objects to allocate + // per attempt. Sized to fill a fair amount of + // the available memory. + private static final int LargeObjSize = 9 * 1024 * 1024; // Large enough to be a humongous object. + + private static Object[] objects; + + private static void test() throws Exception { + + // This task drops the humongous objects, making them eligible for + // uncommit, and starts the concurrent bitmap clearing. While it is + // running, the caller triggers GCs that may or may not trigger the issue. + FutureTask concurrentClearTask = new FutureTask<>(() -> { + objects = null; + WB.concurrentGCRunTo(WB.G1_BEFORE_CLEANUP_COMPLETED); + return null; + }); + + try { + System.out.println("taking control"); + WB.concurrentGCAcquireControl(); + + // Allocate a new set of humongous objects. Acquire control first to avoid + // unnecessary concurrent cycles due to that allocation. We do not need them. + objects = new Object[NumObjs]; + for (int i = 0; i < objects.length; i++) { + objects[i] = new byte[LargeObjSize]; + } + + WB.concurrentGCRunTo(WB.G1_AFTER_CLEANUP_STARTED); + + new Thread(concurrentClearTask).start(); + + int numYoungGCs = 0; + // Execute at least one young GC, even if the concurrent + // clear bitmap finishes very quickly. + do { + WB.youngGC(); + numYoungGCs++; + // Wait a bit. This should give the concurrent clear task a chance + // to finish execution. + Thread.sleep(1); + } while (!concurrentClearTask.isDone() && numYoungGCs < 200); + + concurrentClearTask.get(30, TimeUnit.SECONDS); // Propagates exceptions, if any. + } finally { + WB.concurrentGCRunToIdle(); + + System.out.println("Releasing control"); + WB.concurrentGCReleaseControl(); + } + } + + public static void main(String[] args) throws Exception { + if (!WB.supportsConcurrentGCBreakpoints()) { + throw new RuntimeException("G1 should support GC breakpoints"); + } + for (int i = 0; i < 20; i++) { + test(); + } + } +}