diff --git a/8014628-Support-AES-Encryption-with-HMAC-SHA2-for-Ke.patch b/8014628-Support-AES-Encryption-with-HMAC-SHA2-for-Ke.patch index 08411fd6f00c8cf19db13e61916c1528e037fbc9..df447e6a35706a27fdfbd2349e2c4258a4914258 100644 --- a/8014628-Support-AES-Encryption-with-HMAC-SHA2-for-Ke.patch +++ b/8014628-Support-AES-Encryption-with-HMAC-SHA2-for-Ke.patch @@ -1957,9 +1957,9 @@ index 6413e155b..b59832f73 100644 - * @bug 7152176 8168518 + * @bug 7152176 8168518 8014628 * @summary More krb5 tests - * @library ../../../../java/security/testlibrary/ + * @library ../../../../java/security/testlibrary/ /test/lib * @compile -XDignore.symbol.file ReplayCacheTestProc.java -@@ -126,8 +126,13 @@ public class ReplayCacheTestProc { +@@ -139,8 +139,13 @@ public class ReplayCacheTestProc { kdc.addPrincipalRandKey(service(i)); } @@ -1971,9 +1971,9 @@ index 6413e155b..b59832f73 100644 + // Write KTAB after krb5.conf so it contains no aes-sha2 keys kdc.writeKtab(OneKDC.KTAB); - KDC.saveConfig(OneKDC.KRB5_CONF, kdc); - - // User-provided libs - String userLibs = System.getProperty("test.libs"); + + pi = Proc.create("ReplayCacheTestProc").debug("C") + .args("initiator") diff --git a/jdk/test/sun/security/krb5/etype/ETypeOrder.java b/jdk/test/sun/security/krb5/etype/ETypeOrder.java index 9437b16ed..be36d6372 100644 --- a/jdk/test/sun/security/krb5/etype/ETypeOrder.java diff --git a/8136577_Make_AbortVMOnException_available_in_product_builds.patch b/8136577_Make_AbortVMOnException_available_in_product_builds.patch index 1aa04c7bc9b4677cd2536ad44905707ee88616df..1b13af19532753e32e6a9f3c55ea29944f59ad65 100755 --- a/8136577_Make_AbortVMOnException_available_in_product_builds.patch +++ b/8136577_Make_AbortVMOnException_available_in_product_builds.patch @@ -2,8 +2,8 @@ diff --git a/hotspot/src/share/vm/c1/c1_Runtime1.cpp b/hotspot/src/share/vm/c1/c index 3c1ea7280..b8d866786 100644 --- a/hotspot/src/share/vm/c1/c1_Runtime1.cpp +++ b/hotspot/src/share/vm/c1/c1_Runtime1.cpp -@@ -542,7 +542,7 @@ JRT_ENTRY_NO_ASYNC(static address, exception_handler_for_pc_helper(JavaThread* t - exception->print_value_string(), p2i((address)exception()), nm->method()->print_value_string(), p2i(pc), p2i(thread)); +@@ -544,7 +544,7 @@ JRT_ENTRY_NO_ASYNC(static address, exception_handler_for_pc_helper(JavaThread* t + p2i((address)exception()), nm->method()->print_value_string(), p2i(pc), p2i(thread)); } // for AbortVMOnException flag - NOT_PRODUCT(Exceptions::debug_check_abort(exception)); diff --git a/Backport-6956385-URLConnection.getLastModified-leaks-file-han.patch b/Backport-6956385-URLConnection.getLastModified-leaks-file-han.patch new file mode 100644 index 0000000000000000000000000000000000000000..d05b7ff7eae5ade774ed6192303350f978148bf9 --- /dev/null +++ b/Backport-6956385-URLConnection.getLastModified-leaks-file-han.patch @@ -0,0 +1,168 @@ +From b9649e772450f25e3c5d47ce1a15b3e1afa12017 Mon Sep 17 00:00:00 2001 +Date: Wed, 17 Apr 2024 10:43:54 +0000 +Subject: [PATCH] [Backport]6956385: URLConnection.getLastModified() leaks file handles + for jar:file and file: URLs +--- + .../www/protocol/file/FileURLConnection.java | 6 ++ + .../www/protocol/jar/JarURLConnection.java | 13 ++- + .../protocol/jar/FileURLConnectionLeak.java | 100 ++++++++++++++++++ + 3 files changed, 117 insertions(+), 2 deletions(-) + create mode 100644 jdk/test/sun/net/www/protocol/jar/FileURLConnectionLeak.java + +diff --git a/jdk/src/share/classes/sun/net/www/protocol/file/FileURLConnection.java b/jdk/src/share/classes/sun/net/www/protocol/file/FileURLConnection.java +index 1997cb08c..16f404988 100644 +--- a/jdk/src/share/classes/sun/net/www/protocol/file/FileURLConnection.java ++++ b/jdk/src/share/classes/sun/net/www/protocol/file/FileURLConnection.java +@@ -103,6 +103,12 @@ public class FileURLConnection extends URLConnection { + } + } + ++ public synchronized void closeInputStream() throws IOException { ++ if (is != null) { ++ is.close(); ++ } ++ } ++ + private boolean initializedHeaders = false; + + private void initializeHeaders() { +diff --git a/jdk/src/share/classes/sun/net/www/protocol/jar/JarURLConnection.java b/jdk/src/share/classes/sun/net/www/protocol/jar/JarURLConnection.java +index d7c442442..f1757da78 100644 +--- a/jdk/src/share/classes/sun/net/www/protocol/jar/JarURLConnection.java ++++ b/jdk/src/share/classes/sun/net/www/protocol/jar/JarURLConnection.java +@@ -25,6 +25,8 @@ + + package sun.net.www.protocol.jar; + ++import sun.net.www.protocol.file.FileURLConnection; ++ + import java.io.InputStream; + import java.io.IOException; + import java.io.FileNotFoundException; +@@ -107,8 +109,15 @@ public class JarURLConnection extends java.net.JarURLConnection { + try { + super.close(); + } finally { +- if (!getUseCaches()) { +- jarFile.close(); ++ try { ++ if (!getUseCaches()) { ++ jarFile.close(); ++ } ++ } finally { ++ if (jarFileURLConnection instanceof FileURLConnection) { ++ FileURLConnection fileURLConnection = (FileURLConnection) jarFileURLConnection; ++ fileURLConnection.closeInputStream(); ++ } + } + } + } +diff --git a/jdk/test/sun/net/www/protocol/jar/FileURLConnectionLeak.java b/jdk/test/sun/net/www/protocol/jar/FileURLConnectionLeak.java +new file mode 100644 +index 000000000..4a5f9d7e2 +--- /dev/null ++++ b/jdk/test/sun/net/www/protocol/jar/FileURLConnectionLeak.java +@@ -0,0 +1,100 @@ ++/* ++ * 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 6956385 ++ * @summary JarURLConnection may fail to close its underlying FileURLConnection ++ * @run main/othervm FileURLConnectionLeak ++ */ ++ ++import java.io.InputStream; ++import java.io.OutputStream; ++import java.lang.management.ManagementFactory; ++import java.lang.management.RuntimeMXBean; ++import java.net.URI; ++import java.net.URL; ++import java.net.URLConnection; ++import java.nio.file.Files; ++import java.nio.file.Path; ++import java.nio.file.Paths; ++import java.util.jar.Attributes; ++import java.util.jar.JarOutputStream; ++import java.util.jar.Manifest; ++ ++public class FileURLConnectionLeak { ++ public static void main(String[] args) throws Exception { ++ Path jar = Paths.get("x.jar").toAbsolutePath(); ++ Manifest mani = new Manifest(); ++ mani.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0"); ++ try (OutputStream os = Files.newOutputStream(jar); OutputStream jos = new JarOutputStream(os, mani)) {} ++ URL u = URI.create("jar:" + jar.toUri() + "!/META-INF/MANIFEST.MF").toURL(); ++ URLConnection urlConnection = u.openConnection(); ++ urlConnection.setDefaultUseCaches(false); ++ // FileURLConnection.is not used, so was always fine: ++ try (InputStream is = u.openStream()) { ++ byte[] buffer = new byte[1024]; ++ int bytesRead; ++ while ((bytesRead = is.read(buffer)) != -1) { ++ System.out.write(buffer, 0, bytesRead); ++ } ++ } ++ // FileURLConnection.is opened implicitly: ++ URLConnection conn = u.openConnection(); ++ conn.getLastModified(); ++ // Idiom to close URLConnection (cf. JDK-8224095), which must also close the other stream: ++ conn.getInputStream().close(); ++ Path fds = Paths.get("/proc/" + getPid() + "/fd"); ++ if (Files.isDirectory(fds)) { ++ // Linux: verify that x.jar is not open ++ for (Path fd : (Iterable) Files.list(fds)::iterator) { ++ if (Files.isSymbolicLink(fd)) { ++ Path file = Files.readSymbolicLink(fd); ++ if (file.equals(jar)) { ++ throw new IllegalStateException("Still held open " + jar + " from " + fd); ++ } ++ } ++ } ++ } ++ // Windows: verify that mandatory file locks do not prevent deletion ++ Files.delete(jar); ++ } ++ ++ private static int getPid() { ++ try { ++ // get runtime MXBean ++ RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean(); ++ // get pid ++ String name = runtime.getName(); ++ int index = name.indexOf('@'); ++ if (index != -1) { ++ return Integer.parseInt(name.substring(0, index)); ++ } ++ } catch (Exception e) { ++ e.printStackTrace(); ++ } ++ return -1; ++ } ++ ++ ++} +-- +2.23.0 + diff --git a/Backport-7036144-GZIPInputStream-readTrailer-uses-faulty-avai.patch b/Backport-7036144-GZIPInputStream-readTrailer-uses-faulty-avai.patch new file mode 100644 index 0000000000000000000000000000000000000000..f7ec9900fcbeaad2198169e78c1bb0e79a9f82be --- /dev/null +++ b/Backport-7036144-GZIPInputStream-readTrailer-uses-faulty-avai.patch @@ -0,0 +1,169 @@ +From 8f3c271e9d34a1105f069fb9d3081c72e1c48180 Mon Sep 17 00:00:00 2001 +Date: Tue, 28 May 2024 02:31:27 +0000 +Subject: [PATCH] [Backport]7036144:GZIPInputStream readTrailer uses faulty available() + test for end-of-stream +--- + .../java/util/zip/GZIPInputStream.java | 24 ++-- + .../zip/GZIP/GZIPInputStreamAvailable.java | 112 ++++++++++++++++++ + 2 files changed, 121 insertions(+), 15 deletions(-) + create mode 100644 jdk/test/java/util/zip/GZIP/GZIPInputStreamAvailable.java + +diff --git a/jdk/src/share/classes/java/util/zip/GZIPInputStream.java b/jdk/src/share/classes/java/util/zip/GZIPInputStream.java +index b3d9240ba..0d57e8ab3 100644 +--- a/jdk/src/share/classes/java/util/zip/GZIPInputStream.java ++++ b/jdk/src/share/classes/java/util/zip/GZIPInputStream.java +@@ -224,23 +224,17 @@ class GZIPInputStream extends InflaterInputStream { + (readUInt(in) != (inf.getBytesWritten() & 0xffffffffL))) + throw new ZipException("Corrupt GZIP trailer"); + +- // If there are more bytes available in "in" or +- // the leftover in the "inf" is > 26 bytes: +- // this.trailer(8) + next.header.min(10) + next.trailer(8) + // try concatenated case +- if (this.in.available() > 0 || n > 26) { +- int m = 8; // this.trailer +- try { +- m += readHeader(in); // next.header +- } catch (IOException ze) { +- return true; // ignore any malformed, do nothing +- } +- inf.reset(); +- if (n > m) +- inf.setInput(buf, len - n + m, n - m); +- return false; ++ int m = 8; // this.trailer ++ try { ++ m += readHeader(in); // next.header ++ } catch (IOException ze) { ++ return true; // ignore any malformed, do nothing + } +- return true; ++ inf.reset(); ++ if (n > m) ++ inf.setInput(buf, len - n + m, n - m); ++ return false; + } + + /* +diff --git a/jdk/test/java/util/zip/GZIP/GZIPInputStreamAvailable.java b/jdk/test/java/util/zip/GZIP/GZIPInputStreamAvailable.java +new file mode 100644 +index 000000000..265050b17 +--- /dev/null ++++ b/jdk/test/java/util/zip/GZIP/GZIPInputStreamAvailable.java +@@ -0,0 +1,112 @@ ++/* ++ * 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 7036144 ++ * @summary Test concatenated gz streams when available() returns zero ++ */ ++ ++import java.io.*; ++import java.util.*; ++import java.util.zip.*; ++ ++public class GZIPInputStreamAvailable { ++ ++ public static final int NUM_COPIES = 100; ++ public static void main(String[] args) throws Throwable { ++ testZeroAvailable(); ++ } ++ ++ public static void testZeroAvailable() throws IOException { ++ ++ // Create some uncompressed data and then repeat it NUM_COPIES times ++ byte[] uncompressed1 = "this is a test".getBytes("ASCII"); ++ byte[] uncompressedN = repeat(uncompressed1, NUM_COPIES); ++ ++ // Compress the original data and then repeat that NUM_COPIES times ++ byte[] compressed1 = deflate(uncompressed1); ++ byte[] compressedN = repeat(compressed1, NUM_COPIES); ++ ++ // (a) Read back inflated data from a stream where available() is accurate and verify ++ byte[] readback1 = inflate(new ByteArrayInputStream(compressedN), uncompressedN.length); ++ assertArrayEquals(uncompressedN, readback1); ++ ++ // (b) Read back inflated data from a stream where available() always returns zero and verify ++ byte[] readback2 = inflate(new ZeroAvailableStream(new ByteArrayInputStream(compressedN)), uncompressedN.length); ++ assertArrayEquals(uncompressedN, readback2); ++ } ++ ++ public static byte[] repeat(byte[] data, int count) { ++ byte[] repeat = new byte[data.length * count]; ++ int off = 0; ++ for (int i = 0; i < count; i++) { ++ System.arraycopy(data, 0, repeat, off, data.length); ++ off += data.length; ++ } ++ return repeat; ++ } ++ ++ public static byte[] deflate(byte[] data) throws IOException { ++ ByteArrayOutputStream buf = new ByteArrayOutputStream(); ++ try (GZIPOutputStream out = new GZIPOutputStream(buf)) { ++ out.write(data); ++ } ++ return buf.toByteArray(); ++ } ++ ++ public static byte[] inflate(InputStream in, int bufferLen) throws IOException { ++ GZIPInputStream gzipInputStream = new GZIPInputStream(in); ++ ByteArrayOutputStream bos = new ByteArrayOutputStream(); ++ byte[] buffer = new byte[bufferLen]; ++ int len; ++ while ((len = gzipInputStream.read(buffer)) != -1) { ++ bos.write(buffer, 0, len); ++ } ++ gzipInputStream.close(); ++ bos.close(); ++ return bos.toByteArray(); ++ } ++ ++ public static class ZeroAvailableStream extends FilterInputStream { ++ public ZeroAvailableStream(InputStream in) { ++ super(in); ++ } ++ @Override ++ public int available() { ++ return 0; ++ } ++ } ++ ++ public static void assertArrayEquals(byte[] arr1, byte[] arr2) { ++ if (arr1 == null && arr2 == null) return; ++ if (arr1 != null && arr2 != null && arr1.length == arr2.length) { ++ for (int i = 0; i < arr1.length; i++) { ++ if (arr1[i] != arr2[i]) { ++ throw new AssertionError(Arrays.toString(arr1) + " != " + Arrays.toString(arr2)); ++ } ++ } ++ return; ++ } ++ throw new AssertionError(Arrays.toString(arr1) + " != " + Arrays.toString(arr2)); ++ } ++} +\ No newline at end of file +-- +2.23.0 + diff --git a/Backport-8068864-C2-failed-modified-node-is-not-on-IGVN._work.patch b/Backport-8068864-C2-failed-modified-node-is-not-on-IGVN._work.patch new file mode 100644 index 0000000000000000000000000000000000000000..8ca64dec638048a8d02bb7231e931b8fdcdcc7c3 --- /dev/null +++ b/Backport-8068864-C2-failed-modified-node-is-not-on-IGVN._work.patch @@ -0,0 +1,27 @@ +From 7af1eca9cf66942bf9e54a582f3046ae9b96a8eb Mon Sep 17 00:00:00 2001 +Date: Thu, 23 May 2024 11:28:10 +0800 +Subject: [PATCH] [Backport]8068864: C2 failed: modified node is not on + IGVN._worklist +--- + hotspot/src/share/vm/opto/loopTransform.cpp | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/hotspot/src/share/vm/opto/loopTransform.cpp b/hotspot/src/share/vm/opto/loopTransform.cpp +index 414edc26b..0aca095ce 100644 +--- a/hotspot/src/share/vm/opto/loopTransform.cpp ++++ b/hotspot/src/share/vm/opto/loopTransform.cpp +@@ -2006,10 +2006,9 @@ void PhaseIdealLoop::do_range_check( IdealLoopTree *loop, Node_List &old_new ) { + } + Node *main_cmp = main_bol->in(1); + if( main_cmp->outcnt() > 1 ) { // CmpNode shared? +- _igvn.hash_delete(main_bol); + main_cmp = main_cmp->clone();// Clone a private CmpNode + register_new_node( main_cmp, main_cle->in(0) ); +- main_bol->set_req(1,main_cmp); ++ _igvn.replace_input_of(main_bol, 1, main_cmp); + } + // Hack the now-private loop bounds + _igvn.replace_input_of(main_cmp, 2, main_limit); +-- +2.19.1 + diff --git a/Backport-8151845-Comment-in-globals.hpp-for-MetaspaceSize-is-.patch b/Backport-8151845-Comment-in-globals.hpp-for-MetaspaceSize-is-.patch new file mode 100644 index 0000000000000000000000000000000000000000..e0638156a16827ddea03904c162c2cf08b016f96 --- /dev/null +++ b/Backport-8151845-Comment-in-globals.hpp-for-MetaspaceSize-is-.patch @@ -0,0 +1,39 @@ +From 005d0a4e518c2f41aa1d5fc76110214001532df8 Mon Sep 17 00:00:00 2001 +Date: Wed, 29 May 2024 14:52:13 +0800 +Subject: [PATCH] [Backport]8151845: Comment in globals.hpp for MetaspaceSize is + incorrect. +--- + hotspot/src/share/vm/memory/metaspace.cpp | 2 +- + hotspot/src/share/vm/runtime/globals.hpp | 3 ++- + 2 files changed, 3 insertions(+), 2 deletions(-) + +diff --git a/hotspot/src/share/vm/memory/metaspace.cpp b/hotspot/src/share/vm/memory/metaspace.cpp +index d08bfba84..1df9eb606 100644 +--- a/hotspot/src/share/vm/memory/metaspace.cpp ++++ b/hotspot/src/share/vm/memory/metaspace.cpp +@@ -2599,7 +2599,7 @@ void MetaspaceGC::compute_new_size() { + if (PrintGCDetails && Verbose) { + gclog_or_tty->print_cr(" " + " shrinking:" +- " initSize: %.1fK" ++ " initThreshold: %.1fK" + " maximum_desired_capacity: %.1fK", + MetaspaceSize / (double) K, + maximum_desired_capacity / (double) K); +diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp +index 6aa53d2d2..f3daa12a6 100644 +--- a/hotspot/src/share/vm/runtime/globals.hpp ++++ b/hotspot/src/share/vm/runtime/globals.hpp +@@ -3332,7 +3332,8 @@ class CommandLineFlags { + "non-daemon thread (in bytes)") \ + \ + product_pd(uintx, MetaspaceSize, \ +- "Initial size of Metaspaces (in bytes)") \ ++ "Initial threshold (in bytes) at which a garbage collection " \ ++ "is done to reduce Metaspace usage") \ + \ + product(uintx, MaxMetaspaceSize, max_uintx, \ + "Maximum size of Metaspaces (in bytes)") \ +-- +2.23.0 + diff --git a/Backport-8209362-sun-security-ssl-SSLSocketImpl-ReuseAddr.jav.patch b/Backport-8209362-sun-security-ssl-SSLSocketImpl-ReuseAddr.jav.patch new file mode 100644 index 0000000000000000000000000000000000000000..30b6c933a076edb71729d1c4915383f9095e05f7 --- /dev/null +++ b/Backport-8209362-sun-security-ssl-SSLSocketImpl-ReuseAddr.jav.patch @@ -0,0 +1,305 @@ +From 50df8472137e95ff6f64fe4136bbad64db8b46e7 Mon Sep 17 00:00:00 2001 +Date: Mon, 27 May 2024 15:12:37 +0800 +Subject: [PATCH] 8209362: sun/security/ssl/SSLSocketImpl/ReuseAddr.java failed + due to "BindException: Address already in use (Bind failed)" +--- + .../net/ssl/templates/SSLSocketTemplate.java | 6 +- + .../security/ssl/SSLSocketImpl/ReuseAddr.java | 237 ++---------------- + 2 files changed, 17 insertions(+), 226 deletions(-) + +diff --git a/jdk/test/javax/net/ssl/templates/SSLSocketTemplate.java b/jdk/test/javax/net/ssl/templates/SSLSocketTemplate.java +index 9e09a0e35..e62f57eba 100644 +--- a/jdk/test/javax/net/ssl/templates/SSLSocketTemplate.java ++++ b/jdk/test/javax/net/ssl/templates/SSLSocketTemplate.java +@@ -224,12 +224,12 @@ public class SSLSocketTemplate { + /* + * What's the server port? Use any free port by default + */ +- private volatile int serverPort = 0; ++ protected volatile int serverPort = 0; + + /* + * Define the server side of the test. + */ +- private void doServerSide() throws Exception { ++ protected void doServerSide() throws Exception { + // kick start the server side service + SSLContext context = createServerSSLContext(); + SSLServerSocketFactory sslssf = context.getServerSocketFactory(); +@@ -290,7 +290,7 @@ public class SSLSocketTemplate { + /* + * Define the client side of the test. + */ +- private void doClientSide() throws Exception { ++ protected void doClientSide() throws Exception { + + // Wait for server to get started. + // +diff --git a/jdk/test/sun/security/ssl/SSLSocketImpl/ReuseAddr.java b/jdk/test/sun/security/ssl/SSLSocketImpl/ReuseAddr.java +index 650c30988..abad01099 100644 +--- a/jdk/test/sun/security/ssl/SSLSocketImpl/ReuseAddr.java ++++ b/jdk/test/sun/security/ssl/SSLSocketImpl/ReuseAddr.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2001, 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 +@@ -25,240 +25,31 @@ + * @test + * @bug 4482446 + * @summary java.net.SocketTimeoutException on 98, NT, 2000 for JSSE +- * @run main/othervm ReuseAddr ++ * @library /javax/net/ssl/templates ++ * @run main ReuseAddr + * + * SunJSSE does not support dynamic system properties, no way to re-use + * system properties in samevm/agentvm mode. + * @author Brad Wetmore + */ + +-import java.io.*; +-import java.net.*; +-import javax.net.ssl.*; ++import java.net.ServerSocket; + +-public class ReuseAddr { ++public class ReuseAddr extends SSLSocketTemplate { + +- /* +- * ============================================================= +- * Set the various variables needed for the tests, then +- * specify what tests to run on each side. +- */ ++ @Override ++ protected void doServerSide() throws Exception { ++ super.doServerSide(); + +- /* +- * Should we run the client or server in a separate thread? +- * Both sides can throw exceptions, but do you have a preference +- * as to which side should be the main thread. +- */ +- static boolean separateServerThread = true; +- +- /* +- * Where do we find the keystores? +- */ +- private final static String pathToStores = "../../../../javax/net/ssl/etc"; +- static String keyStoreFile = "keystore"; +- static String trustStoreFile = "truststore"; +- static String passwd = "passphrase"; +- +- /* +- * Is the server ready to serve? +- */ +- volatile static boolean serverReady = false; +- +- /* +- * Turn on SSL debugging? +- */ +- static boolean debug = false; +- +- /* +- * If the client or server is doing some kind of object creation +- * that the other side depends on, and that thread prematurely +- * exits, you may experience a hang. The test harness will +- * terminate all hung threads after its timeout has expired, +- * currently 3 minutes by default, but you might try to be +- * smart about it.... +- */ +- +- /* +- * Define the server side of the test. +- * +- * If the server prematurely exits, serverReady will be set to true +- * to avoid infinite hangs. +- */ +- void doServerSide() throws Exception { +- SSLServerSocketFactory sslssf = +- (SSLServerSocketFactory) SSLServerSocketFactory.getDefault(); +- SSLServerSocket sslServerSocket = +- (SSLServerSocket) sslssf.createServerSocket(serverPort); +- serverPort = sslServerSocket.getLocalPort(); +- +- /* +- * Signal Client, we're ready for his connect. +- */ +- serverReady = true; +- +- SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept(); +- InputStream sslIS = sslSocket.getInputStream(); +- OutputStream sslOS = sslSocket.getOutputStream(); +- +- sslIS.read(); +- sslOS.write(85); +- sslOS.flush(); +- +- sslSocket.close(); +- +- // Close original server socket +- sslServerSocket.close(); +- +- // Try rebinding to same port +- sslServerSocket = +- (SSLServerSocket) sslssf.createServerSocket(serverPort); +- sslServerSocket.close(); +- } +- +- /* +- * Define the client side of the test. +- * +- * If the server prematurely exits, serverReady will be set to true +- * to avoid infinite hangs. +- */ +- void doClientSide() throws Exception { +- +- /* +- * Wait for server to get started. +- */ +- while (!serverReady) { +- Thread.sleep(50); ++ // Note that if this port is already used by another test, ++ // this test will fail. ++ System.out.println("Try rebinding to same port: " + serverPort); ++ try (ServerSocket server = new ServerSocket(serverPort)) { ++ System.out.println("Server port: " + server.getLocalPort()); + } +- +- SSLSocketFactory sslsf = +- (SSLSocketFactory) SSLSocketFactory.getDefault(); +- SSLSocket sslSocket = (SSLSocket) +- sslsf.createSocket("localhost", serverPort); +- +- InputStream sslIS = sslSocket.getInputStream(); +- OutputStream sslOS = sslSocket.getOutputStream(); +- +- sslOS.write(280); +- sslOS.flush(); +- sslIS.read(); +- +- sslSocket.close(); + } + +- /* +- * ============================================================= +- * The remainder is just support stuff +- */ +- +- // use any free port by default +- volatile int serverPort = 0; +- +- volatile Exception serverException = null; +- volatile Exception clientException = null; +- + public static void main(String[] args) throws Exception { +- String keyFilename = +- System.getProperty("test.src", "./") + "/" + pathToStores + +- "/" + keyStoreFile; +- String trustFilename = +- System.getProperty("test.src", "./") + "/" + pathToStores + +- "/" + trustStoreFile; +- +- System.setProperty("javax.net.ssl.keyStore", keyFilename); +- System.setProperty("javax.net.ssl.keyStorePassword", passwd); +- System.setProperty("javax.net.ssl.trustStore", trustFilename); +- System.setProperty("javax.net.ssl.trustStorePassword", passwd); +- +- if (debug) +- System.setProperty("javax.net.debug", "all"); +- +- /* +- * Start the tests. +- */ +- new ReuseAddr(); +- } +- +- Thread clientThread = null; +- Thread serverThread = null; +- +- /* +- * Primary constructor, used to drive remainder of the test. +- * +- * Fork off the other side, then do your work. +- */ +- ReuseAddr() throws Exception { +- if (separateServerThread) { +- startServer(true); +- startClient(false); +- } else { +- startClient(true); +- startServer(false); +- } +- +- /* +- * Wait for other side to close down. +- */ +- if (separateServerThread) { +- serverThread.join(); +- } else { +- clientThread.join(); +- } +- +- /* +- * When we get here, the test is pretty much over. +- * +- * If the main thread excepted, that propagates back +- * immediately. If the other thread threw an exception, we +- * should report back. +- */ +- if (serverException != null) +- throw serverException; +- if (clientException != null) +- throw clientException; +- } +- +- void startServer(boolean newThread) throws Exception { +- if (newThread) { +- serverThread = new Thread() { +- public void run() { +- try { +- doServerSide(); +- } catch (Exception e) { +- /* +- * Our server thread just died. +- * +- * Release the client, if not active already... +- */ +- System.err.println("Server died..."); +- serverReady = true; +- serverException = e; +- } +- } +- }; +- serverThread.start(); +- } else { +- doServerSide(); +- } +- } +- +- void startClient(boolean newThread) throws Exception { +- if (newThread) { +- clientThread = new Thread() { +- public void run() { +- try { +- doClientSide(); +- } catch (Exception e) { +- /* +- * Our client thread just died. +- */ +- System.err.println("Client died..."); +- clientException = e; +- } +- } +- }; +- clientThread.start(); +- } else { +- doClientSide(); +- } ++ new ReuseAddr().run(); + } + } +-- +2.19.1 + diff --git a/Backport-8210706-G1-may-deadlock-when-starting-a-concurrent-c.patch b/Backport-8210706-G1-may-deadlock-when-starting-a-concurrent-c.patch new file mode 100644 index 0000000000000000000000000000000000000000..c5b688c088f58066b253b8f32b58ef176ec97d28 --- /dev/null +++ b/Backport-8210706-G1-may-deadlock-when-starting-a-concurrent-c.patch @@ -0,0 +1,171 @@ +From 8e53927b6739a935dc833f7e9527dacb71bae1a8 Mon Sep 17 00:00:00 2001 +Date: Thu, 30 May 2024 07:02:40 +0000 +Subject: [PATCH] [Backport]8210706: G1 may deadlock when starting a concurrent cycle at + shutdown +--- + .../gc_implementation/g1/concurrentMark.cpp | 20 +++++++++++-------- + .../gc_implementation/g1/concurrentMark.hpp | 4 ++++ + .../g1/concurrentMarkThread.cpp | 8 +++++++- + .../gc_implementation/g1/g1CollectedHeap.cpp | 14 +++++++------ + .../shared/concurrentGCThread.hpp | 2 ++ + 5 files changed, 33 insertions(+), 15 deletions(-) + +diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp +index 1347a7e16..cad474b83 100644 +--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp ++++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp +@@ -477,6 +477,16 @@ HeapRegion* CMRootRegions::claim_next() { + return res; + } + ++void CMRootRegions::notify_scan_done() { ++ MutexLockerEx x(RootRegionScan_lock, Mutex::_no_safepoint_check_flag); ++ _scan_in_progress = false; ++ RootRegionScan_lock->notify_all(); ++} ++ ++void CMRootRegions::cancel_scan() { ++ notify_scan_done(); ++} ++ + void CMRootRegions::scan_finished() { + assert(scan_in_progress(), "pre-condition"); + +@@ -486,11 +496,7 @@ void CMRootRegions::scan_finished() { + } + _next_survivor = NULL; + +- { +- MutexLockerEx x(RootRegionScan_lock, Mutex::_no_safepoint_check_flag); +- _scan_in_progress = false; +- RootRegionScan_lock->notify_all(); +- } ++ notify_scan_done(); + } + + bool CMRootRegions::wait_until_scan_finished() { +@@ -1224,13 +1230,11 @@ public: + }; + + void ConcurrentMark::scanRootRegions() { +- // Start of concurrent marking. +- ClassLoaderDataGraph::clear_claimed_marks(); +- + // scan_in_progress() will have been set to true only if there was + // at least one root region to scan. So, if it's false, we + // should not attempt to do any further work. + if (root_regions()->scan_in_progress()) { ++ assert(!has_aborted(), "Aborting before root region scanning is finished not supported."); + _parallel_marking_threads = calc_parallel_marking_threads(); + assert(parallel_marking_threads() <= max_parallel_marking_threads(), + "Maximum number of marking threads exceeded"); +diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp +index bbd5d590a..172caef29 100644 +--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp ++++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp +@@ -333,6 +333,8 @@ private: + volatile bool _should_abort; + HeapRegion* volatile _next_survivor; + ++ void notify_scan_done(); ++ + public: + CMRootRegions(); + // We actually do most of the initialization in this method. +@@ -352,6 +354,8 @@ public: + // all have been claimed. + HeapRegion* claim_next(); + ++ void cancel_scan(); ++ + // Flag that we're done with root region scanning and notify anyone + // who's waiting on it. If aborted is false, assume that all regions + // have been claimed. +diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp +index 9b0452f92..3c4553bf7 100644 +--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp ++++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp +@@ -23,6 +23,7 @@ + */ + + #include "precompiled.hpp" ++#include "classfile/classLoaderData.hpp" + #include "gc_implementation/g1/concurrentMarkThread.inline.hpp" + #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" + #include "gc_implementation/g1/g1CollectorPolicy.hpp" +@@ -100,6 +101,10 @@ void ConcurrentMarkThread::run() { + HandleMark hm; + double cycle_start = os::elapsedVTime(); + ++ { ++ ClassLoaderDataGraph::clear_claimed_marks(); ++ } ++ + // We have to ensure that we finish scanning the root regions + // before the next GC takes place. To ensure this we have to + // make sure that we do not join the STS until the root regions +@@ -109,7 +114,7 @@ void ConcurrentMarkThread::run() { + // correctness issue. + + double scan_start = os::elapsedTime(); +- if (!cm()->has_aborted()) { ++ { + if (G1Log::fine()) { + gclog_or_tty->gclog_stamp(cm()->concurrent_gc_id()); + gclog_or_tty->print_cr("[GC concurrent-root-region-scan-start]"); +@@ -297,6 +302,7 @@ void ConcurrentMarkThread::run() { + } + } + assert(_should_terminate, "just checking"); ++ _cm->root_regions()->cancel_scan(); + + terminate(); + } +diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +index 5b156f99d..3ff5586c1 100644 +--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp ++++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +@@ -1346,8 +1346,7 @@ bool G1CollectedHeap::do_collection(bool explicit_gc, + ref_processor_cm()->verify_no_references_recorded(); + + // Abandon current iterations of concurrent marking and concurrent +- // refinement, if any are in progress. We have to do this before +- // wait_until_scan_finished() below. ++ // refinement, if any are in progress. + concurrent_mark()->abort(); + + // Make sure we'll choose a new allocation region afterwards. +@@ -4032,10 +4031,13 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) { + verify_region_sets_optional(); + verify_dirty_young_regions(); + +- // This call will decide whether this pause is an initial-mark +- // pause. If it is, during_initial_mark_pause() will return true +- // for the duration of this pause. +- g1_policy()->decide_on_conc_mark_initiation(); ++ // We should not be doing initial mark unless the conc mark thread is running ++ if (!_cmThread->should_terminate()) { ++ // This call will decide whether this pause is an initial-mark ++ // pause. If it is, during_initial_mark_pause() will return true ++ // for the duration of this pause. ++ g1_policy()->decide_on_conc_mark_initiation(); ++ } + + // We do not allow initial-mark to be piggy-backed on a mixed GC. + assert(!g1_policy()->during_initial_mark_pause() || +diff --git a/hotspot/src/share/vm/gc_implementation/shared/concurrentGCThread.hpp b/hotspot/src/share/vm/gc_implementation/shared/concurrentGCThread.hpp +index 1e16bf726..ceb65b029 100644 +--- a/hotspot/src/share/vm/gc_implementation/shared/concurrentGCThread.hpp ++++ b/hotspot/src/share/vm/gc_implementation/shared/concurrentGCThread.hpp +@@ -71,6 +71,8 @@ public: + + // Tester + bool is_ConcurrentGC_thread() const { return true; } ++ ++ bool should_terminate() { return _should_terminate; } + }; + + // The SurrogateLockerThread is used by concurrent GC threads for +-- +2.23.0 + diff --git a/Backport-8318889-Backport-Important-Fixed-Issues-in-Later-Ver.patch b/Backport-8318889-Backport-Important-Fixed-Issues-in-Later-Ver.patch new file mode 100644 index 0000000000000000000000000000000000000000..38c47b873035d7be7f5cb5c5c15c37f0fe687162 --- /dev/null +++ b/Backport-8318889-Backport-Important-Fixed-Issues-in-Later-Ver.patch @@ -0,0 +1,524 @@ +From d9cb35d747e5f38210a3207d6821e333dcf45a8b Mon Sep 17 00:00:00 2001 +Date: Fri, 31 May 2024 15:39:38 +0800 +Subject: [PATCH] [Backport]8318889: Backport Important Fixed Issues in Later Versions + 2024_5_30 +--- + hotspot/src/os/linux/vm/os_perf_linux.cpp | 2 +- + hotspot/src/share/vm/opto/loopnode.cpp | 8 +- + hotspot/src/share/vm/prims/jni.cpp | 5 + + .../abstractMethod/AbstractMethodClass.jasm | 43 ++++++ + .../abstractMethod/TestJNIAbstractMethod.java | 68 +++++++++ + .../jni/abstractMethod/libJNIAbstractMethod.c | 43 ++++++ + .../media/sound/StandardMidiFileReader.java | 13 +- + .../classes/javax/swing/text/html/CSS.java | 6 +- + jdk/src/share/native/java/util/zip/zip_util.c | 2 +- + .../native/sun/awt/image/jpeg/imageioJPEG.c | 4 + + .../native/sun/awt/image/jpeg/jpegdecoder.c | 4 + + .../File/SMFInterruptedRunningStatus.java | 143 ++++++++++++++++++ + 12 files changed, 331 insertions(+), 10 deletions(-) + create mode 100644 hotspot/test/runtime/jni/abstractMethod/AbstractMethodClass.jasm + create mode 100644 hotspot/test/runtime/jni/abstractMethod/TestJNIAbstractMethod.java + create mode 100644 hotspot/test/runtime/jni/abstractMethod/libJNIAbstractMethod.c + create mode 100644 jdk/test/javax/sound/midi/File/SMFInterruptedRunningStatus.java + +diff --git a/hotspot/src/os/linux/vm/os_perf_linux.cpp b/hotspot/src/os/linux/vm/os_perf_linux.cpp +index 0d1f75810..6a92675a6 100644 +--- a/hotspot/src/os/linux/vm/os_perf_linux.cpp ++++ b/hotspot/src/os/linux/vm/os_perf_linux.cpp +@@ -941,7 +941,7 @@ SystemProcessInterface::SystemProcesses::ProcessIterator::ProcessIterator() { + bool SystemProcessInterface::SystemProcesses::ProcessIterator::initialize() { + _dir = os::opendir("/proc"); + _entry = NULL; +- _valid = true; ++ _valid = _dir != NULL; // May be null if /proc is not accessible. + next_process(); + + return true; +diff --git a/hotspot/src/share/vm/opto/loopnode.cpp b/hotspot/src/share/vm/opto/loopnode.cpp +index 5e6d53a48..351e6888b 100644 +--- a/hotspot/src/share/vm/opto/loopnode.cpp ++++ b/hotspot/src/share/vm/opto/loopnode.cpp +@@ -2571,6 +2571,7 @@ void PhaseIdealLoop::build_and_optimize(bool do_split_ifs, bool skip_loop_opts) + NOT_PRODUCT( C->verify_graph_edges(); ) + worklist.push( C->top() ); + build_loop_late( visited, worklist, nstack ); ++ if (C->failing()) { return; } + + if (_verify_only) { + // restore major progress flag +@@ -3781,6 +3782,7 @@ void PhaseIdealLoop::build_loop_late( VectorSet &visited, Node_List &worklist, N + } else { + // All of n's children have been processed, complete post-processing. + build_loop_late_post(n); ++ if (C->failing()) { return; } + if (nstack.is_empty()) { + // Finished all nodes on stack. + // Process next node on the worklist. +@@ -3884,13 +3886,15 @@ void PhaseIdealLoop::build_loop_late_post( Node *n ) { + Node *legal = LCA; // Walk 'legal' up the IDOM chain + Node *least = legal; // Best legal position so far + while( early != legal ) { // While not at earliest legal +-#ifdef ASSERT + if (legal->is_Start() && !early->is_Root()) { ++#ifdef ASSERT + // Bad graph. Print idom path and fail. + dump_bad_graph("Bad graph detected in build_loop_late", n, early, LCA); + assert(false, "Bad graph detected in build_loop_late"); +- } + #endif ++ C->record_method_not_compilable("Bad graph detected in build_loop_late"); ++ return; ++ } + // Find least loop nesting depth + legal = idom(legal); // Bump up the IDOM tree + // Check for lower nesting depth +diff --git a/hotspot/src/share/vm/prims/jni.cpp b/hotspot/src/share/vm/prims/jni.cpp +index de0aae9b4..cccb578ea 100644 +--- a/hotspot/src/share/vm/prims/jni.cpp ++++ b/hotspot/src/share/vm/prims/jni.cpp +@@ -1380,6 +1380,11 @@ static void jni_invoke_nonstatic(JNIEnv *env, JavaValue* result, jobject receive + } + } + ++ if (selected_method->is_abstract()) { ++ ResourceMark rm(THREAD); ++ THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), selected_method->name()->as_C_string()); ++ } ++ + methodHandle method(THREAD, selected_method); + + // Create object to hold arguments for the JavaCall, and associate it with +diff --git a/hotspot/test/runtime/jni/abstractMethod/AbstractMethodClass.jasm b/hotspot/test/runtime/jni/abstractMethod/AbstractMethodClass.jasm +new file mode 100644 +index 000000000..24c53f203 +--- /dev/null ++++ b/hotspot/test/runtime/jni/abstractMethod/AbstractMethodClass.jasm +@@ -0,0 +1,43 @@ ++/* ++ * 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. ++ * ++ */ ++/* ++ * This is a non-abstract class with an abstract method. ++ * ++ */ ++super public class AbstractMethodClass ++ extends java/lang/Object ++ version 51:0 // Java 7 version ++{ ++ ++ public Method "":"()V" ++ stack 1 locals 1 ++ { ++ aload_0; ++ invokespecial Method java/lang/Object."":"()V"; ++ return; ++ } ++ ++ public abstract Method "abstractM":"()V"; ++ ++} +diff --git a/hotspot/test/runtime/jni/abstractMethod/TestJNIAbstractMethod.java b/hotspot/test/runtime/jni/abstractMethod/TestJNIAbstractMethod.java +new file mode 100644 +index 000000000..2384f6d5a +--- /dev/null ++++ b/hotspot/test/runtime/jni/abstractMethod/TestJNIAbstractMethod.java +@@ -0,0 +1,68 @@ ++/* ++ * 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. ++ * ++ */ ++ ++/* ++ * @test ++ * @bug 8323243 ++ * @summary Test that invocation of an abstract method from JNI works correctly ++ * @compile AbstractMethodClass.jasm ++ * @run main/othervm/native TestJNIAbstractMethod ++ */ ++ ++/** ++ * We are testing invocation of an abstract method from JNI - which should ++ * simply result in throwning AbstractMethodError. To invoke an abstract method ++ * we must have an instance method (as abstract static methods are illegal), ++ * but instantiating an abstract class is also illegal at the Java language ++ * level, so we have to use a custom jasm class that contains an abstract method ++ * declaration, but which is not itself declared as an abstract class. ++ */ ++public class TestJNIAbstractMethod { ++ ++ // Invokes an abstract method from JNI and throws AbstractMethodError. ++ private static native void invokeAbstractM(Class AMclass, ++ AbstractMethodClass receiver); ++ ++ static { ++ System.loadLibrary("JNIAbstractMethod"); ++ } ++ ++ public static void main(String[] args) { ++ AbstractMethodClass obj = new AbstractMethodClass(); ++ try { ++ System.out.println("Attempting direct invocation via Java"); ++ obj.abstractM(); ++ throw new RuntimeException("Did not get AbstractMethodError from Java!"); ++ } catch (AbstractMethodError expected) { ++ System.out.println("ok - got expected exception: " + expected); ++ } ++ try { ++ System.out.println("Attempting direct invocation via JNI"); ++ invokeAbstractM(obj.getClass(), obj); ++ throw new RuntimeException("Did not get AbstractMethodError from JNI!"); ++ } catch (AbstractMethodError expected) { ++ System.out.println("ok - got expected exception: " + expected); ++ } ++ } ++} +diff --git a/hotspot/test/runtime/jni/abstractMethod/libJNIAbstractMethod.c b/hotspot/test/runtime/jni/abstractMethod/libJNIAbstractMethod.c +new file mode 100644 +index 000000000..35a28f702 +--- /dev/null ++++ b/hotspot/test/runtime/jni/abstractMethod/libJNIAbstractMethod.c +@@ -0,0 +1,43 @@ ++/* ++ * 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. ++ * ++ */ ++#include ++#include ++#include ++ ++JNIEXPORT void JNICALL Java_TestJNIAbstractMethod_invokeAbstractM(JNIEnv* env, ++ jclass this_cls, ++ jclass target_cls, ++ jobject receiver) { ++ ++ jmethodID mid = (*env)->GetMethodID(env, target_cls, "abstractM", "()V"); ++ if (mid == NULL) { ++ fprintf(stderr, "Error looking up method abstractM\n"); ++ (*env)->ExceptionDescribe(env); ++ exit(1); ++ } ++ ++ printf("Invoking abstract method ...\n"); ++ (*env)->CallVoidMethod(env, receiver, mid); // Should raise exception ++ ++} +diff --git a/jdk/src/share/classes/com/sun/media/sound/StandardMidiFileReader.java b/jdk/src/share/classes/com/sun/media/sound/StandardMidiFileReader.java +index 20ebe4f06..ba7f344a4 100644 +--- a/jdk/src/share/classes/com/sun/media/sound/StandardMidiFileReader.java ++++ b/jdk/src/share/classes/com/sun/media/sound/StandardMidiFileReader.java +@@ -326,10 +326,10 @@ final class SMFParser { + // reset current tick to 0 + long tick = 0; + +- // reset current status byte to 0 (invalid value). ++ // reset current running status byte to 0 (invalid value). + // this should cause us to throw an InvalidMidiDataException if we don't + // get a valid status byte from the beginning of the track. +- int status = 0; ++ int runningStatus = 0; + boolean endOfTrackFound = false; + + while (!trackFinished() && !endOfTrackFound) { +@@ -346,10 +346,17 @@ final class SMFParser { + // check for new status + int byteValue = readUnsigned(); + ++ int status; + if (byteValue >= 0x80) { + status = byteValue; ++ ++ // update running status (only for channel messages) ++ if ((status & 0xF0) != 0xF0) { ++ runningStatus = status; ++ } + } else { +- data1 = byteValue; ++ status = runningStatus; ++ data1 = byteValue; + } + + switch (status & 0xF0) { +diff --git a/jdk/src/share/classes/javax/swing/text/html/CSS.java b/jdk/src/share/classes/javax/swing/text/html/CSS.java +index 4a944d381..4713bcd60 100644 +--- a/jdk/src/share/classes/javax/swing/text/html/CSS.java ++++ b/jdk/src/share/classes/javax/swing/text/html/CSS.java +@@ -2581,8 +2581,8 @@ public class CSS implements Serializable { + * Used for BackgroundImages. + */ + static class BackgroundImage extends CssValue { +- private boolean loadedImage; +- private ImageIcon image; ++ private volatile boolean loadedImage; ++ private ImageIcon image; + + Object parseCssValue(String value) { + BackgroundImage retValue = new BackgroundImage(); +@@ -2600,7 +2600,6 @@ public class CSS implements Serializable { + synchronized(this) { + if (!loadedImage) { + URL url = CSS.getURL(base, svalue); +- loadedImage = true; + if (url != null) { + image = new ImageIcon(); + Image tmpImg = Toolkit.getDefaultToolkit().createImage(url); +@@ -2608,6 +2607,7 @@ public class CSS implements Serializable { + image.setImage(tmpImg); + } + } ++ loadedImage = true; + } + } + } +diff --git a/jdk/src/share/native/java/util/zip/zip_util.c b/jdk/src/share/native/java/util/zip/zip_util.c +index ff59c5ecc..8b0c08909 100644 +--- a/jdk/src/share/native/java/util/zip/zip_util.c ++++ b/jdk/src/share/native/java/util/zip/zip_util.c +@@ -443,7 +443,7 @@ hash(const char *s) + static unsigned int + hashN(const char *s, int length) + { +- int h = 0; ++ unsigned int h = 0; + while (length-- > 0) + h = 31*h + *s++; + return h; +diff --git a/jdk/src/share/native/sun/awt/image/jpeg/imageioJPEG.c b/jdk/src/share/native/sun/awt/image/jpeg/imageioJPEG.c +index 7e1d8c99d..1cd9e8bdb 100644 +--- a/jdk/src/share/native/sun/awt/image/jpeg/imageioJPEG.c ++++ b/jdk/src/share/native/sun/awt/image/jpeg/imageioJPEG.c +@@ -1131,6 +1131,10 @@ imageio_skip_input_data(j_decompress_ptr cinfo, long num_bytes) + return; + } + num_bytes += sb->remaining_skip; ++ // Check for overflow if remaining_skip value is too large ++ if (num_bytes < 0) { ++ return; ++ } + sb->remaining_skip = 0; + + /* First the easy case where we are skipping <= the current contents. */ +diff --git a/jdk/src/share/native/sun/awt/image/jpeg/jpegdecoder.c b/jdk/src/share/native/sun/awt/image/jpeg/jpegdecoder.c +index cea158e17..2f64d33cc 100644 +--- a/jdk/src/share/native/sun/awt/image/jpeg/jpegdecoder.c ++++ b/jdk/src/share/native/sun/awt/image/jpeg/jpegdecoder.c +@@ -406,6 +406,10 @@ sun_jpeg_skip_input_data(j_decompress_ptr cinfo, long num_bytes) + return; + } + num_bytes += src->remaining_skip; ++ // Check for overflow if remaining_skip value is too large ++ if (num_bytes < 0) { ++ return; ++ } + src->remaining_skip = 0; + ret = (int)src->pub.bytes_in_buffer; /* this conversion is safe, because capacity of the buffer is limited by jnit */ + if (ret >= num_bytes) { +diff --git a/jdk/test/javax/sound/midi/File/SMFInterruptedRunningStatus.java b/jdk/test/javax/sound/midi/File/SMFInterruptedRunningStatus.java +new file mode 100644 +index 000000000..1b82e2f73 +--- /dev/null ++++ b/jdk/test/javax/sound/midi/File/SMFInterruptedRunningStatus.java +@@ -0,0 +1,143 @@ ++/* ++ * 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.ByteArrayInputStream; ++ ++import javax.sound.midi.MidiSystem; ++import javax.sound.midi.Sequence; ++import javax.sound.midi.Track; ++ ++/** ++ * @test ++ * @bug 8319598 ++ * @summary SMFParser bug with running status, interrupted by Meta or SysEx messages ++ */ ++public class SMFInterruptedRunningStatus { ++ ++ public static void main(String[] args) throws Exception { ++ ++ byte[][] files = new byte[][] {SMF_1, SMF_2, SMF_3}; ++ for (int i = 0; i < files.length; i++) { ++ Sequence seq = MidiSystem.getSequence( ++ new ByteArrayInputStream(files[i])); ++ testSequence(seq, i + 1); ++ } ++ ++ // no exception thrown, all files have been parsed correctly ++ System.out.println("Test passed"); ++ } ++ ++ private static void testSequence(Sequence seq, int fileNumber) { ++ ++ // check number of tracks and number of events ++ Track[] tracks = seq.getTracks(); ++ if (1 != tracks.length) { ++ throw new RuntimeException("file number " ++ + fileNumber + " fails (incorrect number of tracks: " ++ + tracks.length + ")"); ++ } ++ Track track = tracks[0]; ++ if (7 != track.size()) { ++ throw new RuntimeException("file number " + fileNumber ++ + " fails (incorrect number of events: " ++ + track.size() + ")"); ++ } ++ ++ // check status byte of each message ++ int[] expectedStatusBytes = new int[] { ++ 0x90, 0xFF, 0x90, 0x90, 0x90, 0xFF, 0xFF}; ++ for (int i = 0; i < expectedStatusBytes.length; i++) { ++ int expected = expectedStatusBytes[i]; ++ if (expected != track.get(i).getMessage().getStatus()) { ++ throw new RuntimeException("file number " + fileNumber ++ + " fails (wrong status byte in event " + i + ")"); ++ } ++ } ++ } ++ ++ // MIDI file without running status - should work equally before ++ // and after the bugfix ++ private static final byte[] SMF_1 = { ++ 0x4D, 0x54, 0x68, 0x64, 0x00, 0x00, 0x00, 0x06, // file header (start) ++ 0x00, 0x01, 0x00, 0x01, 0x00, (byte) 0x80, // file header (end) ++ 0x4D, 0x54, 0x72, 0x6B, 0x00, 0x00, 0x00, 0x24, // track header ++ 0x00, // delta time ++ (byte) 0x90, 0x3C, 0x7F, // Note-ON (C) ++ 0x40, // delta time ++ (byte) 0xFF, 0x01, 0x04, 0x54, 0x65, 0x73, 0x74, // META (text) ++ 0x20, // delta time ++ (byte) 0x90, 0x3C, 0x00, // Note-OFF (C) ++ 0x20, // delta time ++ (byte) 0x90, 0x3E, 0x7F, // Note-ON (D) ++ 0x60, // delta time ++ (byte) 0x90, 0x3E, 0x00, // Note-OFF (D) ++ 0x20, // delta time ++ (byte) 0xFF, 0x01, 0x04, 0x54, 0x65, 0x73, 0x74, // META (text) ++ 0x00, // delta time ++ (byte) 0xFF, 0x2F, 0x00 // META (end of track) ++ }; ++ ++ // MIDI file with running status, interrupted by a META message ++ // - failed before the bugfix ++ private static final byte[] SMF_2 = { ++ 0x4D, 0x54, 0x68, 0x64, 0x00, 0x00, 0x00, 0x06, // file header (start) ++ 0x00, 0x01, 0x00, 0x01, 0x00, (byte) 0x80, // file header (end) ++ 0x4D, 0x54, 0x72, 0x6B, 0x00, 0x00, 0x00, 0x21, // track header ++ 0x00, // delta time ++ (byte) 0x90, 0x3C, 0x7F, // Note-ON (C) ++ 0x40, // delta time ++ (byte) 0xFF, 0x01, 0x04, 0x54, 0x65, 0x73, 0x74, // META (interruptor) ++ 0x20, // delta time ++ 0x3C, 0x00, // Note-OFF (C) - running status ++ 0x20, // delta time ++ 0x3E, 0x7F, // Note-ON (D) - running status ++ 0x60, // delta time ++ 0x3E, 0x00, // Note-OFF (D) - running status ++ 0x20, // delta time ++ (byte) 0xFF, 0x01, 0x04, 0x54, 0x65, 0x73, 0x74, // META (text) ++ 0x00, // delta time ++ (byte) 0xFF, 0x2F, 0x00 // META (end of track) ++ }; ++ ++ // MIDI file with running status, interrupted by a META message ++ // - succeeded before the bugfix but with wrong interpretation of the data ++ private static final byte[] SMF_3 = { ++ 0x4D, 0x54, 0x68, 0x64, 0x00, 0x00, 0x00, 0x06, // file header (start) ++ 0x00, 0x01, 0x00, 0x01, 0x00, (byte) 0x80, // file header (end) ++ 0x4D, 0x54, 0x72, 0x6B, 0x00, 0x00, 0x00, 0x21, // track header ++ 0x00, // delta time ++ (byte) 0x90, 0x3C, 0x7F, // Note-ON (C) ++ 0x40, // delta time ++ (byte) 0xFF, 0x01, 0x04, 0x54, 0x65, 0x73, 0x74, // META (interruptor) ++ 0x20, // delta time ++ 0x3C, 0x00, // Note-OFF (C) - running status ++ 0x0D, // delta time ++ 0x3E, 0x7F, // Note-ON (D) - running status ++ 0x60, // delta time ++ 0x3E, 0x00, // Note-OFF (D) - running status ++ 0x20, // delta time ++ (byte) 0xFF, 0x01, 0x04, 0x54, 0x65, 0x73, 0x74, // META (text) ++ 0x00, // delta time ++ (byte) 0xFF, 0x2F, 0x00 // META (end of track) ++ }; ++} +-- +2.23.0 + diff --git a/Dynamic-CDS-Archive.patch b/Dynamic-CDS-Archive.patch index 30a6ff8169def8d3ed47633f5431a0b3a19d72dd..ebeb75b4dc1d0728436d76fb24b392d380f8f398 100644 --- a/Dynamic-CDS-Archive.patch +++ b/Dynamic-CDS-Archive.patch @@ -3070,12 +3070,13 @@ index 8dd4e6b21..6a2d8077f 100644 // We take care not to be blocking while holding the // SymbolTable_lock. Otherwise, the system might deadlock, since the // symboltable is used during compilation (VM_thread) The lock free -@@ -236,12 +267,32 @@ unsigned int SymbolTable::hash_symbol(const char* s, int len) { - // entries in the symbol table during normal execution (only during - // safepoints). +@@ -251,13 +282,33 @@ unsigned int SymbolTable::hash_symbol(const char* s, int len) { + return len; + } -Symbol* SymbolTable::lookup(const char* name, int len, TRAPS) { +Symbol* SymbolTable::lookup_common(const char* name, int len) { + len = check_length(name, len); unsigned int hashValue = hash_symbol(name, len); int index = the_table()->hash_to_index(hashValue); + Symbol* s; diff --git a/Huawei-Add-Aggressive-CDS.patch b/Huawei-Add-Aggressive-CDS.patch new file mode 100644 index 0000000000000000000000000000000000000000..b6085e33d4f2d9d972b214dd0b34a1b6d1f92924 --- /dev/null +++ b/Huawei-Add-Aggressive-CDS.patch @@ -0,0 +1,1316 @@ +From a7acbdd7c7885a92e3e62d485c0ceaa95923806f Mon Sep 17 00:00:00 2001 +Date: Mon, 27 May 2024 16:14:55 +0800 +Subject: [PATCH] [Huawei]Add Aggressive CDS +--- + hotspot/make/bsd/makefiles/mapfile-vers-debug | 1 + + .../make/bsd/makefiles/mapfile-vers-product | 1 + + .../make/linux/makefiles/mapfile-vers-debug | 1 + + .../make/linux/makefiles/mapfile-vers-product | 1 + + hotspot/src/share/vm/cds/archiveBuilder.cpp | 5 + + hotspot/src/share/vm/cds/dynamicArchive.cpp | 20 + + .../share/vm/classfile/classFileParser.cpp | 32 ++ + .../vm/classfile/systemDictionaryShared.cpp | 375 ++++++++++++++++++ + .../vm/classfile/systemDictionaryShared.hpp | 13 + + hotspot/src/share/vm/classfile/vmSymbols.hpp | 2 + + hotspot/src/share/vm/memory/filemap.cpp | 53 ++- + hotspot/src/share/vm/memory/filemap.hpp | 11 + + hotspot/src/share/vm/prims/jvm.cpp | 30 ++ + hotspot/src/share/vm/prims/jvm.h | 6 + + hotspot/src/share/vm/runtime/arguments.cpp | 16 + + hotspot/src/share/vm/runtime/arguments.hpp | 4 + + hotspot/src/share/vm/runtime/globals.hpp | 8 + + hotspot/src/share/vm/utilities/macros.hpp | 9 + + jdk/make/mapfiles/libjava/mapfile-linux | 1 + + jdk/make/mapfiles/libjava/mapfile-vers | 1 + + .../share/classes/java/lang/ClassLoader.java | 35 ++ + .../classes/java/net/AggressiveCDSPlugin.java | 45 +++ + .../classes/java/net/URLClassLoader.java | 27 ++ + .../java/security/ProtectionDomain.java | 16 + + .../java/security/SecureClassLoader.java | 12 + + .../share/classes/sun/misc/URLClassPath.java | 18 + + jdk/src/share/javavm/export/jvm.h | 5 + + jdk/src/share/native/java/lang/ClassLoader.c | 25 ++ + 28 files changed, 772 insertions(+), 1 deletion(-) + create mode 100644 jdk/src/share/classes/java/net/AggressiveCDSPlugin.java + +diff --git a/hotspot/make/bsd/makefiles/mapfile-vers-debug b/hotspot/make/bsd/makefiles/mapfile-vers-debug +index c60ad3e00..86af8a1be 100644 +--- a/hotspot/make/bsd/makefiles/mapfile-vers-debug ++++ b/hotspot/make/bsd/makefiles/mapfile-vers-debug +@@ -233,6 +233,7 @@ + _JVM_AdaptiveHeapGetG1PeriodicGCInterval + _JVM_AdaptiveHeapSetG1PeriodicGCLoadThreshold + _JVM_AdaptiveHeapGetG1PeriodicGCLoadThreshold ++ _JVM_DefineTrustedSharedClass + _JVM_Sleep + _JVM_Socket + _JVM_SocketAvailable +diff --git a/hotspot/make/bsd/makefiles/mapfile-vers-product b/hotspot/make/bsd/makefiles/mapfile-vers-product +index 94d123c9f..69cd3f962 100644 +--- a/hotspot/make/bsd/makefiles/mapfile-vers-product ++++ b/hotspot/make/bsd/makefiles/mapfile-vers-product +@@ -233,6 +233,7 @@ + _JVM_AdaptiveHeapGetG1PeriodicGCLoadThreshold + _JVM_AdaptiveHeapSetG1PeriodicGCInterval + _JVM_AdaptiveHeapSetG1PeriodicGCLoadThreshold ++ _JVM_DefineTrustedSharedClass + _JVM_Sleep + _JVM_Socket + _JVM_SocketAvailable +diff --git a/hotspot/make/linux/makefiles/mapfile-vers-debug b/hotspot/make/linux/makefiles/mapfile-vers-debug +index 1ebe436cb..b006a84c2 100644 +--- a/hotspot/make/linux/makefiles/mapfile-vers-debug ++++ b/hotspot/make/linux/makefiles/mapfile-vers-debug +@@ -237,6 +237,7 @@ SUNWprivate_1.1 { + JVM_AdaptiveHeapGetG1PeriodicGCInterval; + JVM_AdaptiveHeapSetG1PeriodicGCLoadThreshold; + JVM_AdaptiveHeapGetG1PeriodicGCLoadThreshold; ++ JVM_DefineTrustedSharedClass; + JVM_Sleep; + JVM_Socket; + JVM_SocketAvailable; +diff --git a/hotspot/make/linux/makefiles/mapfile-vers-product b/hotspot/make/linux/makefiles/mapfile-vers-product +index 75e527894..64ccc47fb 100644 +--- a/hotspot/make/linux/makefiles/mapfile-vers-product ++++ b/hotspot/make/linux/makefiles/mapfile-vers-product +@@ -237,6 +237,7 @@ SUNWprivate_1.1 { + JVM_AdaptiveHeapGetG1PeriodicGCInterval; + JVM_AdaptiveHeapSetG1PeriodicGCLoadThreshold; + JVM_AdaptiveHeapGetG1PeriodicGCLoadThreshold; ++ JVM_DefineTrustedSharedClass; + JVM_Sleep; + JVM_Socket; + JVM_SocketAvailable; +diff --git a/hotspot/src/share/vm/cds/archiveBuilder.cpp b/hotspot/src/share/vm/cds/archiveBuilder.cpp +index 13a620028..decd638e0 100644 +--- a/hotspot/src/share/vm/cds/archiveBuilder.cpp ++++ b/hotspot/src/share/vm/cds/archiveBuilder.cpp +@@ -772,7 +772,12 @@ void ArchiveBuilder::clean_up_src_obj_table() { + } + + void ArchiveBuilder::write_archive(FileMapInfo* mapinfo) { ++#if INCLUDE_AGGRESSIVE_CDS ++ assert(mapinfo->header()->magic() == (UseAggressiveCDS ? ++ CDS_AGGRESSIVE_ARCHIVE_MAGIC : CDS_DYNAMIC_ARCHIVE_MAGIC), "Dynamic CDS or Aggressive CDS calls only"); ++#else + assert(mapinfo->header()->magic() == CDS_DYNAMIC_ARCHIVE_MAGIC, "Dynamic CDS calls only"); ++#endif // INCLUDE_AGGRESSIVE_CDS + + mapinfo->write_dynamic_header(); + +diff --git a/hotspot/src/share/vm/cds/dynamicArchive.cpp b/hotspot/src/share/vm/cds/dynamicArchive.cpp +index a623c5b00..2e5ab9385 100644 +--- a/hotspot/src/share/vm/cds/dynamicArchive.cpp ++++ b/hotspot/src/share/vm/cds/dynamicArchive.cpp +@@ -165,6 +165,16 @@ void DynamicArchiveBuilder::init_header() { + + FileMapInfo* base_info = FileMapInfo::current_info(); + _header->set_base_header_crc(base_info->header()->crc()); ++ ++#if INCLUDE_AGGRESSIVE_CDS ++ if (UseAggressiveCDS) { ++ int crc = FileMapInfo::DynamicArchiveHeader::get_current_program_crc(); ++ _header->set_program_crc(crc); ++ } else { ++ _header->set_program_crc(0); ++ } ++#endif // INCLUDE_AGGRESSIVE_CDS ++ + for (int i = 0; i < MetaspaceShared::n_regions; i++) { + _header->set_base_region_crc(i, base_info->header()->space_crc(i)); + } +@@ -401,6 +411,16 @@ bool DynamicArchive::validate(FileMapInfo* dynamic_info) { + return false; + } + ++#if INCLUDE_AGGRESSIVE_CDS ++ // Check the program crc ++ if (UseAggressiveCDS) { ++ if (dynamic_header->program_crc() != FileMapInfo::DynamicArchiveHeader::get_current_program_crc()) { ++ FileMapInfo::fail_continue("Aggressive Dynamic archive cannot be used: program crc verification failed."); ++ return false; ++ } ++ } ++#endif // INCLUDE_AGGRESSIVE_CDS ++ + // Check each space's crc + for (int i = 0; i < MetaspaceShared::n_regions; i++) { + if (dynamic_header->base_region_crc(i) != base_info->space_crc(i)) { +diff --git a/hotspot/src/share/vm/classfile/classFileParser.cpp b/hotspot/src/share/vm/classfile/classFileParser.cpp +index b9fde38dc..8f1b2d47a 100644 +--- a/hotspot/src/share/vm/classfile/classFileParser.cpp ++++ b/hotspot/src/share/vm/classfile/classFileParser.cpp +@@ -4416,6 +4416,38 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, + if (DynamicDumpSharedSpaces && !SystemDictionary::is_builtin_loader(class_loader)) { + this_klass->set_shared_classpath_index(UNREGISTERED_INDEX); + SystemDictionaryShared::set_shared_class_misc_info(this_klass(), cfs); ++#if INCLUDE_AGGRESSIVE_CDS ++ if (UseAggressiveCDS && protection_domain() != NULL) { ++ ResourceMark rm(THREAD); ++ KlassHandle protectionDomain_klass(THREAD, SystemDictionary::ProtectionDomain_klass()); ++ JavaValue result(T_OBJECT); ++ JavaCalls::call_virtual(&result, ++ protection_domain, ++ protectionDomain_klass, ++ vmSymbols::getLocationNoFragString_name(), ++ vmSymbols::void_string_signature(), ++ THREAD); ++ if (!HAS_PENDING_EXCEPTION) { ++ oop res_oop = (oop) result.get_jobject(); ++ if (res_oop != NULL) { ++ char* string_value = java_lang_String::as_utf8_string(res_oop); ++ if (strlen(string_value) != 0) { ++ SystemDictionaryShared::set_url_string(this_klass(), string_value); ++ SystemDictionaryShared::save_timestamp(this_klass(), string_value); ++ } ++ } ++ } else { ++ char* ex_msg = const_cast(""); ++ oop message = java_lang_Throwable::message(PENDING_EXCEPTION); ++ if (message != NULL) { ++ ex_msg = java_lang_String::as_utf8_string(message); ++ } ++ dynamic_cds_log->print_cr("get LocationNoFragString from protection_domain has encountered exception: %s %s", ++ PENDING_EXCEPTION->klass()->external_name(), ex_msg); ++ CLEAR_PENDING_EXCEPTION; ++ } ++ } ++#endif // INCLUDE_AGGRESSIVE_CDS + } + #endif // INCLUDE_CDS + +diff --git a/hotspot/src/share/vm/classfile/systemDictionaryShared.cpp b/hotspot/src/share/vm/classfile/systemDictionaryShared.cpp +index 3a601ee37..7707d6ac6 100644 +--- a/hotspot/src/share/vm/classfile/systemDictionaryShared.cpp ++++ b/hotspot/src/share/vm/classfile/systemDictionaryShared.cpp +@@ -35,6 +35,10 @@ + #include "utilities/resourceHash.hpp" + #include "runtime/mutexLocker.hpp" + #include "utilities/ostream.hpp" ++#if INCLUDE_AGGRESSIVE_CDS ++#include "memory/oopFactory.hpp" ++#include "runtime/javaCalls.hpp" ++#endif // INCLUDE_AGGRESSIVE_CDS + + DEBUG_ONLY(bool SystemDictionaryShared::_no_class_loading_should_happen = false;) + bool SystemDictionaryShared::_dump_in_progress = false; +@@ -68,6 +72,14 @@ public: + } + }; + ++#if INCLUDE_AGGRESSIVE_CDS ++ struct DTSharedClassFile { ++ int length; ++ u1 data[1]; ++ int obj_size() { return ((int)sizeof(length)) + length; } ++ }; ++#endif // INCLUDE_AGGRESSIVE_CDS ++ + InstanceKlass* _klass; + InstanceKlass* _nest_host; + bool _failed_verification; +@@ -78,6 +90,10 @@ public: + GrowableArray* _verifier_constraints; + GrowableArray* _verifier_constraint_flags; + GrowableArray* _loader_constraints; ++#if INCLUDE_AGGRESSIVE_CDS ++ DTSharedClassFile* _url_string; ++ int64_t _classfile_timestamp; ++#endif // INCLUDE_AGGRESSIVE_CDS + + DumpTimeSharedClassInfo() { + _klass = NULL; +@@ -92,6 +108,10 @@ public: + _verifier_constraints = NULL; + _verifier_constraint_flags = NULL; + _loader_constraints = NULL; ++#if INCLUDE_AGGRESSIVE_CDS ++ _url_string = NULL; ++ _classfile_timestamp = 0; ++#endif // INCLUDE_AGGRESSIVE_CDS + } + + void add_verification_constraint(InstanceKlass* k, Symbol* name, +@@ -149,6 +169,44 @@ public: + void set_failed_verification() { _failed_verification = true; } + InstanceKlass* nest_host() const { return _nest_host; } + void set_nest_host(InstanceKlass* nest_host) { _nest_host = nest_host; } ++ ++#if INCLUDE_AGGRESSIVE_CDS ++ DTSharedClassFile* url_string() { ++ return _url_string; ++ } ++ ++ size_t url_string_size() { ++ if (_url_string != NULL) { ++ return (size_t)(_url_string->obj_size()); ++ } ++ return (size_t)0; ++ } ++ ++ void copy_url_string(char* string_value) { ++ assert(strlen(string_value) != 0, "sanity"); ++ size_t string_len = strlen(string_value) + (size_t)1; ++ size_t size = offset_of(DTSharedClassFile, data) + string_len; ++ _url_string = (DTSharedClassFile*) NEW_C_HEAP_ARRAY(u1, size, mtInternal); ++ _url_string->length = (int)string_len; ++ memcpy(_url_string->data, string_value, string_len); ++ assert((int)size == _url_string->obj_size(), "sanity"); ++ } ++ ++ void free_url_string() { ++ if (_url_string != NULL) { ++ FREE_C_HEAP_ARRAY(u1, _url_string, mtInternal); ++ _url_string = NULL; ++ } ++ } ++ ++ int64_t classfile_timestamp() { ++ return _classfile_timestamp; ++ } ++ ++ void set_classfile_timestamp(int64_t classfile_timestamp) { ++ _classfile_timestamp = classfile_timestamp; ++ } ++#endif // INCLUDE_AGGRESSIVE_CDS + }; + + inline unsigned DumpTimeSharedClassTable_hash(InstanceKlass* const& k) { +@@ -245,7 +303,18 @@ public: + } + }; + ++#if INCLUDE_AGGRESSIVE_CDS ++ struct RTSharedClassFile { ++ int length; ++ u1 data[1]; ++ }; ++#endif // INCLUDE_AGGRESSIVE_CDS ++ + InstanceKlass* _klass; ++#if INCLUDE_AGGRESSIVE_CDS ++ RTSharedClassFile* _url_string; ++ int64_t _classfile_timestamp; ++#endif // INCLUDE_AGGRESSIVE_CDS + int _num_verifier_constraints; + int _num_loader_constraints; + +@@ -294,6 +363,17 @@ public: + verifier_constraint_flags_size(num_verifier_constraints); + } + ++#if INCLUDE_AGGRESSIVE_CDS ++ static size_t byte_size(DumpTimeSharedClassInfo& info) { ++ size_t previous_size = byte_size(info._klass, info.num_verifier_constraints(), info.num_loader_constraints()); ++ if (UseAggressiveCDS) { ++ size_t cf_size = info.url_string_size(); ++ if (cf_size != 0) return align_up(previous_size, sizeof(int)) + cf_size; ++ } ++ return previous_size; ++ } ++#endif // INCLUDE_AGGRESSIVE_CDS ++ + private: + size_t crc_offset() const { + return header_size_size(); +@@ -321,6 +401,13 @@ private: + assert(0 <= i && i < _num_loader_constraints, "sanity"); + } + ++#if INCLUDE_AGGRESSIVE_CDS ++ size_t url_string_offset() const { ++ return align_up(verifier_constraint_flags_offset() + verifier_constraint_flags_size(_num_verifier_constraints), ++ sizeof(int)); ++ } ++#endif // INCLUDE_AGGRESSIVE_CDS ++ + public: + CrcInfo* crc() const { + assert(crc_size(_klass) > 0, "must be"); +@@ -350,6 +437,20 @@ public: + return loader_constraints() + i; + } + ++#if INCLUDE_AGGRESSIVE_CDS ++ RTSharedClassFile* url_string() { ++ return (RTSharedClassFile*)(address(this) + url_string_offset()); ++ } ++ ++ int64_t classfile_timestamp() { ++ return _classfile_timestamp; ++ } ++ ++ void set_classfile_timestamp(int64_t classfile_timestamp) { ++ _classfile_timestamp = classfile_timestamp; ++ } ++#endif // INCLUDE_AGGRESSIVE_CDS ++ + void init(DumpTimeSharedClassInfo& info) { + ArchiveBuilder* builder = ArchiveBuilder::current(); + assert(builder->is_in_buffer_space(info._klass), "must be"); +@@ -383,6 +484,18 @@ public: + } + } + ++#if INCLUDE_AGGRESSIVE_CDS ++ if (info.url_string_size() != 0) { ++ _url_string = url_string(); ++ memcpy(_url_string, info.url_string(), info.url_string_size()); ++ ArchivePtrMarker::mark_pointer(&_url_string); ++ info.free_url_string(); ++ } else { ++ _url_string = NULL; ++ } ++ set_classfile_timestamp(info.classfile_timestamp()); ++#endif // INCLUDE_AGGRESSIVE_CDS ++ + ArchivePtrMarker::mark_pointer(&_klass); + } + +@@ -426,6 +539,69 @@ public: + const RunTimeSharedClassInfo* value, Symbol* key, int len_unused) { + return (value->_klass->name() == key); + } ++ ++#if INCLUDE_AGGRESSIVE_CDS ++ // check timestamp in the load time when UseAggressiveCDS. ++ // regular_file(*.class): need to check timestamp. ++ // jar_file(*.jar): no need to check timestamp here,already check programe_crc ++ // somewhere else, see DynamicArchive::validate. ++ // other_file: not supported when UseAggressiveCDS. ++ bool check_classfile_timestamp(char* url_string, TRAPS) { ++ if (SystemDictionaryShared::is_regular_file(url_string)) { ++ ResourceMark rm(THREAD); ++ char* dir = SystemDictionaryShared::get_filedir(url_string); ++ if (dir == NULL) { ++ return false; ++ } ++ int64_t timestamp = SystemDictionaryShared::get_timestamp(dir, _klass->name()); ++ if (timestamp != _classfile_timestamp) { ++ dynamic_cds_log->print_cr("%s, timestamp mismatch: " INT64_FORMAT " -> " INT64_FORMAT, _klass->name()->as_C_string(), _classfile_timestamp, timestamp); ++ return false; ++ } ++ } else if (!SystemDictionaryShared::is_jar_file(url_string)) { ++ dynamic_cds_log->print_cr("Unsupported URL:%s", url_string); ++ return false; ++ } ++ return true; ++ } ++ ++ Handle get_protection_domain(Handle class_loader, TRAPS) { ++ if (_url_string == NULL) { ++ return Handle(); ++ } ++ char* data_ptr = (char*)(_url_string->data); ++ ++ if (CheckClassFileTimeStamp) { ++ if (!check_classfile_timestamp(data_ptr, THREAD)) { ++ return Handle(); ++ } ++ } ++ ++ Handle url_string = java_lang_String::create_from_str(data_ptr, THREAD); ++ JavaValue result(T_OBJECT); ++ JavaCalls::call_virtual(&result, ++ class_loader, ++ class_loader->klass(), ++ vmSymbols::getProtectionDomainByURLString_name(), ++ vmSymbols::getProtectionDomainInternal_signature(), ++ url_string, THREAD); ++ if (!HAS_PENDING_EXCEPTION) { ++ oop pd = (oop) result.get_jobject(); ++ return Handle(THREAD, pd); ++ } else { ++ ResourceMark rm(THREAD); ++ char* ex_msg = const_cast(""); ++ oop message = java_lang_Throwable::message(PENDING_EXCEPTION); ++ if (message != NULL) { ++ ex_msg = java_lang_String::as_utf8_string(message); ++ } ++ dynamic_cds_log->print_cr("get protection_domain has encountered exception: %s %s", ++ PENDING_EXCEPTION->klass()->external_name(), ex_msg); ++ CLEAR_PENDING_EXCEPTION; ++ } ++ return Handle(); ++ } ++#endif // INCLUDE_AGGRESSIVE_CDS + }; + + class RunTimeSharedDictionary : public OffsetCompactHashtable< +@@ -710,7 +886,11 @@ public: + + bool do_entry(InstanceKlass* k, DumpTimeSharedClassInfo& info) { + if (!info.is_excluded()) { ++#if INCLUDE_AGGRESSIVE_CDS ++ size_t byte_size = RunTimeSharedClassInfo::byte_size(info); ++#else + size_t byte_size = RunTimeSharedClassInfo::byte_size(info._klass, info.num_verifier_constraints(), info.num_loader_constraints()); ++#endif // INCLUDE_AGGRESSIVE_CDS + _shared_class_info_size += align_up(byte_size, KlassAlignmentInBytes); + } + return true; // keep on iterating +@@ -746,6 +926,38 @@ unsigned int SystemDictionaryShared::hash_for_shared_dictionary(address ptr) { + } + } + ++#if INCLUDE_AGGRESSIVE_CDS ++class ExcludeDuplicateKlass : StackObj { ++public: ++ static const int INITIAL_TABLE_SIZE = 15889; ++ ++ ExcludeDuplicateKlass(int size) : _has_been_visited(size) {} ++ ++ bool do_entry(InstanceKlass* k, DumpTimeSharedClassInfo& info) { ++ if (!info.is_excluded()) { ++ bool created; ++ Symbol* name = info._klass->name(); ++ address* info_ptr = _has_been_visited.add_if_absent((address)name, (address)&info, &created); ++ if (!created) { ++ info.set_excluded(); ++ DumpTimeSharedClassInfo* first_info = (DumpTimeSharedClassInfo*)(*info_ptr); ++ if (!first_info->is_excluded()) { ++ first_info->set_excluded(); ++ } ++ if (TraceDynamicCDS) { ++ ResourceMark rm; ++ dynamic_cds_log->print_cr("[AggressiveCDS] Skipping duplicate class (excluded): %s", name->as_C_string()); ++ } ++ } ++ } ++ return true; ++ } ++ ++private: ++ KVHashtable _has_been_visited; ++}; ++#endif // INCLUDE_AGGRESSIVE_CDS ++ + class CopySharedClassInfoToArchive : StackObj { + CompactHashtableWriter* _writer; + bool _is_builtin; +@@ -757,7 +969,11 @@ public: + + bool do_entry(InstanceKlass* k, DumpTimeSharedClassInfo& info) { + if (!info.is_excluded() && info.is_builtin() == _is_builtin) { ++#if INCLUDE_AGGRESSIVE_CDS ++ size_t byte_size = RunTimeSharedClassInfo::byte_size(info); ++#else + size_t byte_size = RunTimeSharedClassInfo::byte_size(info._klass, info.num_verifier_constraints(), info.num_loader_constraints()); ++#endif // INCLUDE_AGGRESSIVE_CDS + RunTimeSharedClassInfo* record; + record = (RunTimeSharedClassInfo*)ArchiveBuilder::ro_region_alloc(byte_size); + record->init(info); +@@ -787,6 +1003,12 @@ void SystemDictionaryShared::write_dictionary(RunTimeSharedDictionary* dictionar + bool is_builtin) { + CompactHashtableStats stats; + dictionary->reset(); ++#if INCLUDE_AGGRESSIVE_CDS ++ if (UseAggressiveCDS && !is_builtin) { ++ ExcludeDuplicateKlass dup(ExcludeDuplicateKlass::INITIAL_TABLE_SIZE); ++ _dumptime_table->iterate(&dup); ++ } ++#endif // INCLUDE_AGGRESSIVE_CDS + CompactHashtableWriter writer(_dumptime_table->count_of(is_builtin), &stats); + CopySharedClassInfoToArchive copy(&writer, is_builtin); + assert_lock_strong(DumpTimeTable_lock); +@@ -909,3 +1131,156 @@ InstanceKlass* SystemDictionaryShared::find_dynamic_builtin_class(Symbol* name) + return NULL; + } + } ++ ++#if INCLUDE_AGGRESSIVE_CDS ++static const char* JAR_FILE_PREFIX = "jar://file:"; ++static const char* FILE_SEPARATOR = "file://"; ++static const char* CLASSFILE_SUFFIX = ".class"; ++ ++static bool start_with(char* str, const char* prefix) { ++ if (str == NULL || prefix == NULL || strlen(str) < strlen(prefix)) { ++ return false; ++ } ++ if (strncmp(str, prefix, strlen(prefix)) == 0) { ++ return true; ++ } ++ return false; ++} ++ ++bool SystemDictionaryShared::is_jar_file(char* url_string) { ++ if (start_with(url_string, JAR_FILE_PREFIX)) { ++ return true; ++ } ++ return false; ++} ++ ++bool SystemDictionaryShared::is_regular_file(char* url_string) { ++ if (start_with(url_string, FILE_SEPARATOR)) { ++ return true; ++ } ++ return false; ++} ++ ++char* SystemDictionaryShared::get_filedir(char* url_string) { ++ if (!is_regular_file(url_string)) { ++ return NULL; ++ } ++ char* dir = url_string + strlen(FILE_SEPARATOR); ++ struct stat st; ++ if (os::stat(dir, &st) == 0) { ++ if ((st.st_mode & S_IFDIR) == S_IFDIR) { ++ return dir; ++ } ++ } ++ return NULL; ++} ++ ++int64_t SystemDictionaryShared::get_timestamp(char* dir, Symbol* class_name) { ++ char* name = class_name->as_C_string(); ++ size_t name_len = strlen(name); ++ size_t dir_len = strlen(dir); ++ size_t classfile_suffix_len = strlen(CLASSFILE_SUFFIX); ++ char* file_path = NEW_RESOURCE_ARRAY(char, dir_len + name_len + classfile_suffix_len + 1); ++ memcpy(file_path, dir, dir_len); ++ memcpy(file_path + dir_len, name, name_len); ++ memcpy(file_path + dir_len + name_len, CLASSFILE_SUFFIX, classfile_suffix_len + 1); ++ assert(strlen(file_path) == dir_len + name_len + classfile_suffix_len, "sanity"); ++ struct stat st; ++ if (os::stat(file_path, &st) == 0) { ++ return st.st_mtime; ++ } ++ dynamic_cds_log->print_cr("get timestamp failed:%s", file_path); ++ return 0; ++} ++ ++Handle SystemDictionaryShared::get_protection_domain(InstanceKlass* k, Handle class_loader, TRAPS) { ++ assert(UseAggressiveCDS, "sanity"); ++ RunTimeSharedClassInfo* info = RunTimeSharedClassInfo::get_for(k); ++ assert(!is_builtin_loader(class_loader), "sanity"); ++ return info->get_protection_domain(class_loader, THREAD); ++} ++ ++void SystemDictionaryShared::set_url_string(InstanceKlass* k, char* string_value) { ++ assert(UseAggressiveCDS, "sanity"); ++ Arguments::assert_is_dumping_archive(); ++ assert(!is_builtin(k), "must be unregistered class"); ++ DumpTimeSharedClassInfo* info = find_or_allocate_info_for(k); ++ if (info != NULL && info->_url_string == NULL) { ++ info->copy_url_string(string_value); ++ } ++} ++ ++void SystemDictionaryShared::save_timestamp(InstanceKlass* k, char* string_value) { ++ if (SystemDictionaryShared::is_regular_file(string_value)) { ++ char* dir = SystemDictionaryShared::get_filedir(string_value); ++ if (dir != NULL) { ++ int64_t timestamp = SystemDictionaryShared::get_timestamp(dir, k->name()); ++ SystemDictionaryShared::set_classfile_timestamp(k, timestamp); ++ } ++ } else if (!SystemDictionaryShared::is_jar_file(string_value)) { ++ dynamic_cds_log->print_cr("Unsupported URL:%s", string_value); ++ } ++} ++ ++void SystemDictionaryShared::set_classfile_timestamp(InstanceKlass* k, int64_t classfile_timestamp) { ++ assert(UseAggressiveCDS, "sanity"); ++ Arguments::assert_is_dumping_archive(); ++ assert(!is_builtin(k), "must be unregistered class"); ++ DumpTimeSharedClassInfo* info = find_or_allocate_info_for(k); ++ if (info != NULL) { ++ info->set_classfile_timestamp(classfile_timestamp); ++ } ++} ++ ++InstanceKlass* SystemDictionaryShared::lookup_trusted_share_class(Symbol* class_name, ++ Handle class_loader, ++ TRAPS) { ++ assert(UseAggressiveCDS, "sanity"); ++ if (!UseSharedSpaces) { ++ return NULL; ++ } ++ if (class_name == NULL) { // don't do this for hidden classes ++ return NULL; ++ } ++ if (SystemDictionary::is_builtin_loader(class_loader)) { ++ // Do nothing for the BUILTIN loaders. ++ return NULL; ++ } ++ ++ // Classloaders that support parallelism, e.g. bootstrap classloader, ++ // or all classloaders with UnsyncloadClass do not acquire lock here ++ bool DoObjectLock = true; ++ if (is_parallelCapable(class_loader)) { ++ DoObjectLock = false; ++ } ++ ++ register_loader(class_loader, CHECK_NULL); ++ ++ // Make sure we are synchronized on the class loader before we proceed ++ Handle lockObject = compute_loader_lock_object(class_loader, THREAD); ++ check_loader_lock_contention(lockObject, THREAD); ++ ObjectLocker ol(lockObject, THREAD, DoObjectLock); ++ ++ const RunTimeSharedClassInfo* record = find_record(&_dynamic_unregistered_dictionary, class_name); ++ if (record == NULL) { ++ return NULL; ++ } ++ ++ Handle protection_domain = SystemDictionaryShared::get_protection_domain(record->_klass, class_loader, CHECK_NULL); ++ ++ if (protection_domain.is_null()) { ++ // URL not matched, which means should not be loaded by this classloader ++ return NULL; ++ } ++ ++ instanceKlassHandle k = acquire_class_for_current_thread(record->_klass, class_loader, protection_domain, NULL, THREAD); ++ if (!HAS_PENDING_EXCEPTION && k() != NULL) { ++ if (is_parallelCapable(class_loader)) { ++ k = find_or_define_instance_class(class_name, class_loader, k, THREAD); ++ } else { ++ define_instance_class(k, THREAD); ++ } ++ } ++ return k(); ++} ++#endif // INCLUDE_AGGRESSIVE_CDS +\ No newline at end of file +diff --git a/hotspot/src/share/vm/classfile/systemDictionaryShared.hpp b/hotspot/src/share/vm/classfile/systemDictionaryShared.hpp +index fb9583d4e..3025e7350 100644 +--- a/hotspot/src/share/vm/classfile/systemDictionaryShared.hpp ++++ b/hotspot/src/share/vm/classfile/systemDictionaryShared.hpp +@@ -238,6 +238,19 @@ public: + TRAPS); + + static InstanceKlass* find_dynamic_builtin_class(Symbol* name); ++ ++#if INCLUDE_AGGRESSIVE_CDS ++ static bool is_jar_file(char* url_string); ++ static bool is_regular_file(char* url_string); ++ static char* get_filedir(char* url_string); ++ static int64_t get_timestamp(char* dir, Symbol* class_name); ++ static Handle get_protection_domain(InstanceKlass* k, Handle class_loader, TRAPS); ++ static void set_url_string(InstanceKlass* k, char* string_value); ++ static void save_timestamp(InstanceKlass* k, char* string_value); ++ static void set_classfile_timestamp(InstanceKlass* k, int64_t classfile_timestamp); ++ static int64_t get_classfile_timestamp(InstanceKlass* k); ++ static InstanceKlass* lookup_trusted_share_class(Symbol* class_name, Handle class_loader, TRAPS); ++#endif // INCLUDE_AGGRESSIVE_CDS + }; + + #endif // SHARE_VM_CLASSFILE_SYSTEMDICTIONARYSHARED_HPP +diff --git a/hotspot/src/share/vm/classfile/vmSymbols.hpp b/hotspot/src/share/vm/classfile/vmSymbols.hpp +index 79f15589f..2ddc6581e 100644 +--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp ++++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp +@@ -421,6 +421,8 @@ + template(definePackageInternal_signature, "(Ljava/lang/String;Ljava/util/jar/Manifest;Ljava/net/URL;)V") \ + template(getProtectionDomainInternal_name, "getProtectionDomainInternal") \ + template(getProtectionDomainInternal_signature, "(Ljava/lang/String;)Ljava/security/ProtectionDomain;") \ ++ template(getProtectionDomainByURLString_name, "getProtectionDomainByURLString") \ ++ template(getLocationNoFragString_name, "getLocationNoFragString") \ + template(url_code_signer_array_void_signature, "(Ljava/net/URL;[Ljava/security/CodeSigner;)V") \ + template(resolved_references_name, "") \ + template(referencequeue_null_name, "NULL") \ +diff --git a/hotspot/src/share/vm/memory/filemap.cpp b/hotspot/src/share/vm/memory/filemap.cpp +index 166fe2b80..b60d77be6 100644 +--- a/hotspot/src/share/vm/memory/filemap.cpp ++++ b/hotspot/src/share/vm/memory/filemap.cpp +@@ -208,7 +208,11 @@ size_t FileMapInfo::DynamicArchiveHeader::data_size() { + } + + bool FileMapInfo::DynamicArchiveHeader::validate() { ++#if INCLUDE_AGGRESSIVE_CDS ++ if (_magic != (UseAggressiveCDS ? CDS_AGGRESSIVE_ARCHIVE_MAGIC : CDS_DYNAMIC_ARCHIVE_MAGIC)) { ++#else + if (_magic != CDS_DYNAMIC_ARCHIVE_MAGIC) { ++#endif // INCLUDE_AGGRESSIVE_CDS + FileMapInfo::fail_continue("The shared archive file has a bad magic number."); + return false; + } +@@ -243,9 +247,48 @@ bool FileMapInfo::DynamicArchiveHeader::validate() { + return true; + } + ++#if INCLUDE_AGGRESSIVE_CDS ++int FileMapInfo::DynamicArchiveHeader::get_current_program_crc() { ++ int cur_crc = 0; ++ const char* full_cmd = Arguments::java_command(); ++ if (full_cmd == NULL) { ++ return 0; ++ } ++ const char* main_path = Arguments::get_appclasspath(); ++ int main_path_len = strlen(main_path); ++ bool is_jar_file = strncmp(full_cmd, main_path, main_path_len) == 0; ++ if (is_jar_file) { ++ fio_fd fd = os::open(main_path, O_RDONLY | O_BINARY, 0); ++ assert(fd >= 0, "sanity"); ++ ++ uint32_t file_size = (uint32_t) os::lseek(fd, 0, SEEK_END); ++ os::lseek(fd, 0, SEEK_SET); ++ uint32_t max_size = 40 * 1024 * 1024; // 40M ++ ++ ResourceMark rm; ++ char* buf = NEW_RESOURCE_ARRAY(char, max_size); ++ ++ while(file_size) { ++ uint32_t size = MIN2(max_size, file_size); ++ size_t n = os::read(fd, buf, (unsigned int)size); ++ file_size -= n; ++ cur_crc = ClassLoader::crc32(cur_crc, buf, n); ++ } ++ } ++ return cur_crc; ++} ++#endif // INCLUDE_AGGRESSIVE_CDS ++ + void FileMapInfo::FileMapHeader::populate(FileMapInfo* mapinfo, size_t alignment) { + if (DynamicDumpSharedSpaces) { +- _magic = CDS_DYNAMIC_ARCHIVE_MAGIC; ++#if INCLUDE_AGGRESSIVE_CDS ++ if (UseAggressiveCDS) { ++ _magic = CDS_AGGRESSIVE_ARCHIVE_MAGIC; ++ } else ++#endif // INCLUDE_AGGRESSIVE_CDS ++ { ++ _magic = CDS_DYNAMIC_ARCHIVE_MAGIC; ++ } + } else { + _magic = CDS_ARCHIVE_MAGIC; + } +@@ -434,7 +477,11 @@ bool FileMapInfo::get_base_archive_name_from_header(const char* archive_name, + os::close(fd); + return false; + } ++#if INCLUDE_AGGRESSIVE_CDS ++ if (dynamic_header->magic() != (UseAggressiveCDS ? CDS_AGGRESSIVE_ARCHIVE_MAGIC : CDS_DYNAMIC_ARCHIVE_MAGIC)) { ++#else + if (dynamic_header->magic() != CDS_DYNAMIC_ARCHIVE_MAGIC) { ++#endif // INCLUDE_AGGRESSIVE_CDS + // Not a dynamic header, no need to proceed further. + *size = 0; + delete dynamic_header; +@@ -499,7 +546,11 @@ bool FileMapInfo::check_archive(const char* archive_name, bool is_static) { + } + } else { + DynamicArchiveHeader* dynamic_header = (DynamicArchiveHeader*)header; ++#if INCLUDE_AGGRESSIVE_CDS ++ if (dynamic_header->magic() != (UseAggressiveCDS ? CDS_AGGRESSIVE_ARCHIVE_MAGIC : CDS_DYNAMIC_ARCHIVE_MAGIC)) { ++#else + if (dynamic_header->magic() != CDS_DYNAMIC_ARCHIVE_MAGIC) { ++#endif // INCLUDE_AGGRESSIVE_CDS + delete header; + os::close(fd); + vm_exit_during_initialization("Not a top shared archive", archive_name); +diff --git a/hotspot/src/share/vm/memory/filemap.hpp b/hotspot/src/share/vm/memory/filemap.hpp +index f6cf43a64..c246f0367 100644 +--- a/hotspot/src/share/vm/memory/filemap.hpp ++++ b/hotspot/src/share/vm/memory/filemap.hpp +@@ -41,6 +41,7 @@ + + #define CDS_ARCHIVE_MAGIC 0xf00baba2 + #define CDS_DYNAMIC_ARCHIVE_MAGIC 0xf00baba8 ++#define CDS_AGGRESSIVE_ARCHIVE_MAGIC 0xf00baba4 + + static const int JVM_IDENT_MAX = 256; + +@@ -168,6 +169,9 @@ public: + struct DynamicArchiveHeader : FileMapHeader { + private: + int _base_header_crc; ++#if INCLUDE_AGGRESSIVE_CDS ++ int _program_crc; ++#endif // INCLUDE_AGGRESSIVE_CDS + int _base_region_crc[MetaspaceShared::n_regions]; + char* _requested_base_address; // Archive relocation is not necessary if we map with this base address. + size_t _ptrmap_size_in_bits; // Size of pointer relocation bitmap +@@ -186,6 +190,11 @@ public: + _base_region_crc[i] = c; + } + ++#if INCLUDE_AGGRESSIVE_CDS ++ int program_crc() const { return _program_crc; } ++ void set_program_crc(int c) { _program_crc = c; } ++#endif // INCLUDE_AGGRESSIVE_CDS ++ + void set_requested_base(char* b) { + _requested_base_address = b; + } +@@ -199,6 +208,8 @@ public: + char* serialized_data() const { return from_mapped_offset(_serialized_data_offset); } + + virtual bool validate(); ++ ++ static int get_current_program_crc(); + }; + + FileMapHeader * _header; +diff --git a/hotspot/src/share/vm/prims/jvm.cpp b/hotspot/src/share/vm/prims/jvm.cpp +index 55667ac32..2cc38cf66 100644 +--- a/hotspot/src/share/vm/prims/jvm.cpp ++++ b/hotspot/src/share/vm/prims/jvm.cpp +@@ -3321,6 +3321,36 @@ JVM_ENTRY(jint, JVM_AdaptiveHeapGetG1PeriodicGCLoadThreshold(JNIEnv *env, jclass + #endif + JVM_END + ++JVM_ENTRY(jclass, JVM_DefineTrustedSharedClass(JNIEnv *env, const char *name, jobject loader)) ++#if INCLUDE_AGGRESSIVE_CDS ++ assert(UseAggressiveCDS, "sanity"); ++ ++ TempNewSymbol class_name = NULL; ++ if (name != NULL) { ++ const int str_len = (int)strlen(name); ++ if (str_len > Symbol::max_length()) { ++ // It's impossible to create this class; the name cannot fit ++ // into the constant pool. ++ THROW_MSG_0(vmSymbols::java_lang_NoClassDefFoundError(), name); ++ } ++ class_name = SymbolTable::new_symbol(name, str_len, CHECK_NULL); ++ } ++ ++ ResourceMark rm(THREAD); ++ Handle class_loader (THREAD, JNIHandles::resolve(loader)); ++ InstanceKlass* k = SystemDictionaryShared::lookup_trusted_share_class(class_name, ++ class_loader, ++ CHECK_NULL); ++ if (k == NULL) { ++ return NULL; ++ } ++ ++ return (jclass) JNIHandles::make_local(THREAD, k->java_mirror()); ++#else ++ return NULL; ++#endif // INCLUDE_AGGRESSIVE_CDS ++JVM_END ++ + JVM_ENTRY(void, JVM_Yield(JNIEnv *env, jclass threadClass)) + JVMWrapper("JVM_Yield"); + if (os::dont_yield()) return; +diff --git a/hotspot/src/share/vm/prims/jvm.h b/hotspot/src/share/vm/prims/jvm.h +index 0f22f7b12..46a65604c 100644 +--- a/hotspot/src/share/vm/prims/jvm.h ++++ b/hotspot/src/share/vm/prims/jvm.h +@@ -1598,6 +1598,12 @@ JNIEXPORT jint JNICALL + JVM_AdaptiveHeapGetG1PeriodicGCLoadThreshold(JNIEnv *env, jclass clazz); + + ++/** ++ * Define the trusted shared class. ++ */ ++JNIEXPORT jclass JNICALL ++JVM_DefineTrustedSharedClass(JNIEnv *env, const char *name, jobject loader); ++ + /* ========================================================================= + * The following defines a private JVM interface that the JDK can query + * for the JVM version and capabilities. sun.misc.Version defines +diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp +index 45fbc1423..557695791 100644 +--- a/hotspot/src/share/vm/runtime/arguments.cpp ++++ b/hotspot/src/share/vm/runtime/arguments.cpp +@@ -4356,6 +4356,11 @@ jint Arguments::apply_ergo() { + + ArgumentsExt::set_gc_specific_flags(); + ++#if INCLUDE_AGGRESSIVE_CDS ++ result = init_aggressive_cds_properties(); ++ if (result != JNI_OK) return result; ++#endif // INCLUDE_AGGRESSIVE_CDS ++ + // Initialize Metaspace flags and alignments. + Metaspace::ergo_initialize(); + +@@ -4640,3 +4645,14 @@ bool Arguments::copy_expand_pid(const char* src, size_t srclen, + *b = '\0'; + return (p == src_end); // return false if not all of the source was copied + } ++ ++#if INCLUDE_AGGRESSIVE_CDS ++jint Arguments::init_aggressive_cds_properties() { ++ if (!is_dumping_archive() && SharedDynamicArchivePath != NULL && UseAggressiveCDS) { ++ bool added = false; ++ added = add_property("jdk.jbooster.aggressivecds.load=true"); ++ if (!added) return JNI_ENOMEM; ++ } ++ return JNI_OK; ++} ++#endif // INCLUDE_AGGRESSIVE_CDS +\ No newline at end of file +diff --git a/hotspot/src/share/vm/runtime/arguments.hpp b/hotspot/src/share/vm/runtime/arguments.hpp +index 4f7232e48..fdd1d14b0 100644 +--- a/hotspot/src/share/vm/runtime/arguments.hpp ++++ b/hotspot/src/share/vm/runtime/arguments.hpp +@@ -576,6 +576,10 @@ class Arguments : AllStatic { + assert(Arguments::is_dumping_archive(), "dump time only"); + } + ++#if INCLUDE_AGGRESSIVE_CDS ++ static jint init_aggressive_cds_properties(); ++#endif // INCLUDE_AGGRESSIVE_CDS ++ + static bool CompileMethod(char* className, char* methodName) { + return + methodExists( +diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp +index 77a4ff0b2..6aa53d2d2 100644 +--- a/hotspot/src/share/vm/runtime/globals.hpp ++++ b/hotspot/src/share/vm/runtime/globals.hpp +@@ -4119,6 +4119,14 @@ class CommandLineFlags { + product(bool, UseAppCDS, false, \ + "Enable Application Class Data Sharing (AppCDS)") \ + \ ++ experimental(bool, UseAggressiveCDS, false, \ ++ "An aggressive stratage to improve start-up " \ ++ "because we avoid decoding the classfile.") \ ++ \ ++ experimental(bool, CheckClassFileTimeStamp, true, \ ++ "Check whether the modification time of the" \ ++ "class file is changed during UseAggressiveCDS.") \ ++ \ + product(bool, EnableSplitVerifierForAppCDS, false, \ + "Enable Type Check (AppCDS)") \ + \ +diff --git a/hotspot/src/share/vm/utilities/macros.hpp b/hotspot/src/share/vm/utilities/macros.hpp +index 599e1074d..f631c94c4 100644 +--- a/hotspot/src/share/vm/utilities/macros.hpp ++++ b/hotspot/src/share/vm/utilities/macros.hpp +@@ -106,6 +106,7 @@ + + #ifndef INCLUDE_CDS + #define INCLUDE_CDS 1 ++#define INCLUDE_AGGRESSIVE_CDS 1 + #endif + + #if INCLUDE_CDS +@@ -120,6 +121,14 @@ + #define NOT_CDS_RETURN_(code) { return code; } + #endif // INCLUDE_CDS + ++#if INCLUDE_AGGRESSIVE_CDS ++#define AGGRESSIVE_CDS_ONLY(x) x ++#define NOT_AGGRESSIVE_CDS(x) ++#else ++#define AGGRESSIVE_CDS_ONLY(x) ++#define NOT_AGGRESSIVE_CDS(x) x ++#endif // INCLUDE_AGGRESSIVE_CDS ++ + #ifndef INCLUDE_MANAGEMENT + #define INCLUDE_MANAGEMENT 1 + #endif // INCLUDE_MANAGEMENT +diff --git a/jdk/make/mapfiles/libjava/mapfile-linux b/jdk/make/mapfiles/libjava/mapfile-linux +index ae118af70..61ec28513 100644 +--- a/jdk/make/mapfiles/libjava/mapfile-linux ++++ b/jdk/make/mapfiles/libjava/mapfile-linux +@@ -129,6 +129,7 @@ SUNWprivate_1.1 { + Java_java_lang_ClassLoader_defineClass0; + Java_java_lang_ClassLoader_defineClass1; + Java_java_lang_ClassLoader_defineClass2; ++ Java_java_lang_ClassLoader_defineClass3; + Java_java_lang_ClassLoader_findBuiltinLib; + Java_java_lang_ClassLoader_findLoadedClass0; + Java_java_lang_ClassLoader_resolveClass0; +diff --git a/jdk/make/mapfiles/libjava/mapfile-vers b/jdk/make/mapfiles/libjava/mapfile-vers +index 896db04f2..abfde04a9 100644 +--- a/jdk/make/mapfiles/libjava/mapfile-vers ++++ b/jdk/make/mapfiles/libjava/mapfile-vers +@@ -129,6 +129,7 @@ SUNWprivate_1.1 { + Java_java_lang_ClassLoader_defineClass0; + Java_java_lang_ClassLoader_defineClass1; + Java_java_lang_ClassLoader_defineClass2; ++ Java_java_lang_ClassLoader_defineClass3; + Java_java_lang_ClassLoader_findBuiltinLib; + Java_java_lang_ClassLoader_findLoadedClass0; + Java_java_lang_ClassLoader_resolveClass0; +diff --git a/jdk/src/share/classes/java/lang/ClassLoader.java b/jdk/src/share/classes/java/lang/ClassLoader.java +index f305c1e36..d659eff0f 100644 +--- a/jdk/src/share/classes/java/lang/ClassLoader.java ++++ b/jdk/src/share/classes/java/lang/ClassLoader.java +@@ -682,6 +682,20 @@ public abstract class ClassLoader { + } + } + ++ /** ++ * Determine protection domain, and check it. ++ * This method is only for AggressiveCDS. ++ * ++ * @param name the name of the class ++ * @param c the class ++ * @param pd the ProtectionDomain of the class ++ */ ++ private void defineClassProtectionDomain(String name, Class c, ProtectionDomain pd) ++ { ++ pd = preDefineClass(name, pd); ++ postDefineClass(c, pd); ++ } ++ + /** + * Converts an array of bytes into an instance of class Class, + * with an optional ProtectionDomain. If the domain is +@@ -857,6 +871,27 @@ public abstract class ClassLoader { + int off, int len, ProtectionDomain pd, + String source); + ++ /** ++ * This method is only invoked when java.net.AggressiveCDSPlugin enabled. ++ */ ++ private native Class defineClass3(String name); ++ ++ protected final Class defineClass(String name) { ++ Class trustedClass = defineClass3(name); ++ if (trustedClass != null) { ++ ProtectionDomain pd = AccessController.doPrivileged( ++ new PrivilegedAction() { ++ @Override ++ public ProtectionDomain run() { ++ return trustedClass.getProtectionDomain(); ++ } ++ } ++ ); ++ defineClassProtectionDomain(name, trustedClass, pd); ++ } ++ return trustedClass; ++ } ++ + // true if the name is null or has the potential to be a valid binary name + private boolean checkName(String name) { + if ((name == null) || (name.length() == 0)) +diff --git a/jdk/src/share/classes/java/net/AggressiveCDSPlugin.java b/jdk/src/share/classes/java/net/AggressiveCDSPlugin.java +new file mode 100644 +index 000000000..90d1cd78a +--- /dev/null ++++ b/jdk/src/share/classes/java/net/AggressiveCDSPlugin.java +@@ -0,0 +1,45 @@ ++/* ++ * Copyright (c) 2020, 2023, Huawei Technologies Co., Ltd. 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 java.net; ++ ++import java.security.AccessController; ++import sun.security.action.GetBooleanAction; ++ ++/** ++ * The Aggressive CDS plugin for {@link java.net.URLClassLoader}. ++ */ ++final class AggressiveCDSPlugin { ++ private static final boolean IS_ENABLED = ++ AccessController.doPrivileged( ++ new GetBooleanAction("jdk.jbooster.aggressivecds.load")); ++ ++ /** ++ * Check whether Aggressive CDS is enabled. ++ * ++ * @return Is Aggressive CDS enabled ++ */ ++ public static boolean isEnabled() { ++ return IS_ENABLED; ++ } ++} +\ No newline at end of file +diff --git a/jdk/src/share/classes/java/net/URLClassLoader.java b/jdk/src/share/classes/java/net/URLClassLoader.java +index 876a88842..495964ee7 100644 +--- a/jdk/src/share/classes/java/net/URLClassLoader.java ++++ b/jdk/src/share/classes/java/net/URLClassLoader.java +@@ -382,6 +382,17 @@ public class URLClassLoader extends SecureClassLoader implements Closeable { + result = AccessController.doPrivileged( + new PrivilegedExceptionAction>() { + public Class run() throws ClassNotFoundException { ++ if (AggressiveCDSPlugin.isEnabled()) { ++ Class trustedClass = defineClass(name); ++ if (trustedClass != null) { ++ int i = name.lastIndexOf('.'); ++ if (i != -1) { ++ String pkgname = name.substring(0, i); ++ definePackageInternal(pkgname, null, null); ++ } ++ return trustedClass; ++ } ++ } + String path = name.replace('.', '/').concat(".class"); + Resource res = ucp.getResource(path, false); + if (res != null) { +@@ -409,6 +420,22 @@ public class URLClassLoader extends SecureClassLoader implements Closeable { + return result; + } + ++ /** ++ * get ProtectionDomain By URL String. ++ * This method is invoked only in C++ for AggressiveCDS. ++ * ++ * @param urlNoFragString the URL String. ++ * ++ * @return ProtectionDomain create from URL. ++ */ ++ protected ProtectionDomain getProtectionDomainByURLString(String urlNoFragString) { ++ URL url = ucp.getURL(urlNoFragString); ++ if (url != null) { ++ return getProtectionDomainFromURL(url); ++ } ++ return null; ++ } ++ + /* + * Retrieve the package using the specified package name. + * If non-null, verify the package using the specified code +diff --git a/jdk/src/share/classes/java/security/ProtectionDomain.java b/jdk/src/share/classes/java/security/ProtectionDomain.java +index 7a86115e2..727dc4427 100644 +--- a/jdk/src/share/classes/java/security/ProtectionDomain.java ++++ b/jdk/src/share/classes/java/security/ProtectionDomain.java +@@ -25,6 +25,7 @@ + + package java.security; + ++import java.net.URL; + import java.util.ArrayList; + import java.util.Collections; + import java.util.Enumeration; +@@ -35,6 +36,7 @@ import sun.misc.JavaSecurityAccess; + import sun.misc.JavaSecurityProtectionDomainAccess; + import static sun.misc.JavaSecurityProtectionDomainAccess.ProtectionDomainCache; + import sun.misc.SharedSecrets; ++import sun.net.util.URLUtil; + import sun.security.util.Debug; + import sun.security.util.SecurityConstants; + +@@ -206,6 +208,20 @@ public class ProtectionDomain { + return this.codesource; + } + ++ /** ++ * Returns a URL String. ++ * ++ * @return URL String. ++ */ ++ public String getLocationNoFragString() { ++ if (codesource != null) { ++ URL url = codesource.getLocation(); ++ if (url != null) { ++ return URLUtil.urlNoFragString(url); ++ } ++ } ++ return null; ++ } + + /** + * Returns the ClassLoader of this domain. +diff --git a/jdk/src/share/classes/java/security/SecureClassLoader.java b/jdk/src/share/classes/java/security/SecureClassLoader.java +index cb5f017ba..4b0570104 100644 +--- a/jdk/src/share/classes/java/security/SecureClassLoader.java ++++ b/jdk/src/share/classes/java/security/SecureClassLoader.java +@@ -215,6 +215,18 @@ public class SecureClassLoader extends ClassLoader { + return pd; + } + ++ /** ++ * get ProtectionDomain From URL. ++ * This method is only for AggressiveCDS. ++ * ++ * @param url the URL. ++ * ++ * @return ProtectionDomain create from URL. ++ */ ++ protected ProtectionDomain getProtectionDomainFromURL(URL url) { ++ CodeSource cs = new CodeSource(url, (CodeSigner[]) null); ++ return getProtectionDomain(cs); ++ } + + /* + * Check to make sure the class loader has been initialized. +diff --git a/jdk/src/share/classes/sun/misc/URLClassPath.java b/jdk/src/share/classes/sun/misc/URLClassPath.java +index 70a194f50..6b4987cf3 100644 +--- a/jdk/src/share/classes/sun/misc/URLClassPath.java ++++ b/jdk/src/share/classes/sun/misc/URLClassPath.java +@@ -255,6 +255,24 @@ public class URLClassPath { + return null; + } + ++ /** ++ * Finds the URL which has the specified name. ++ * This method is only for AggressiveCDS. ++ * ++ * @param urlNoFragString the name of URL ++ * @return the URL, or null if not found ++ */ ++ public URL getURL(String urlNoFragString) { ++ if (!urls.isEmpty()) { ++ int index = loaders.size(); ++ while(getLoader(index) != null) { ++ index++; ++ } ++ } ++ Loader loader = lmap.get(urlNoFragString); ++ return loader != null ? loader.getBaseURL() : null; ++ } ++ + /** + * Finds all resources on the URL search path with the given name. + * Returns an enumeration of the URL objects. +diff --git a/jdk/src/share/javavm/export/jvm.h b/jdk/src/share/javavm/export/jvm.h +index d27055622..c37f2ad34 100644 +--- a/jdk/src/share/javavm/export/jvm.h ++++ b/jdk/src/share/javavm/export/jvm.h +@@ -1441,6 +1441,11 @@ JVM_AdaptiveHeapSetG1PeriodicGCLoadThreshold(JNIEnv *env, jclass clazz, jint loa + JNIEXPORT jint JNICALL + JVM_AdaptiveHeapGetG1PeriodicGCLoadThreshold(JNIEnv *env, jclass clazz); + ++/** ++ * Define the trusted shared class. ++ */ ++JNIEXPORT jclass JNICALL ++JVM_DefineTrustedSharedClass(JNIEnv *env, const char *name, jobject loader); + + /* ========================================================================= + * The following defines a private JVM interface that the JDK can query +diff --git a/jdk/src/share/native/java/lang/ClassLoader.c b/jdk/src/share/native/java/lang/ClassLoader.c +index 40b0b85bc..a5515f72f 100644 +--- a/jdk/src/share/native/java/lang/ClassLoader.c ++++ b/jdk/src/share/native/java/lang/ClassLoader.c +@@ -224,6 +224,31 @@ Java_java_lang_ClassLoader_defineClass2(JNIEnv *env, + return result; + } + ++JNIEXPORT jclass JNICALL ++Java_java_lang_ClassLoader_defineClass3(JNIEnv *env, ++ jobject loader, ++ jstring name) ++{ ++ char *utfName; ++ jclass result = 0; ++ char buf[128]; ++ ++ if (name != NULL) { ++ utfName = getUTF(env, name, buf, sizeof(buf)); ++ if (utfName == NULL) { ++ JNU_ThrowOutOfMemoryError(env, NULL); ++ return result; ++ } ++ VerifyFixClassname(utfName); ++ } else { ++ utfName = NULL; ++ } ++ ++ result = JVM_DefineTrustedSharedClass(env, utfName, loader); ++ ++ return result; ++} ++ + JNIEXPORT void JNICALL + Java_java_lang_ClassLoader_resolveClass0(JNIEnv *env, jobject this, + jclass cls) +-- +2.23.0 + diff --git a/Huawei-Keep-objects-when-remove-unshareable-info.patch b/Huawei-Keep-objects-when-remove-unshareable-info.patch new file mode 100644 index 0000000000000000000000000000000000000000..a6be5d65cec746c71616456ce6d3599365b2db8b --- /dev/null +++ b/Huawei-Keep-objects-when-remove-unshareable-info.patch @@ -0,0 +1,97 @@ +From 844511f2b4b6a4be079fc5ac2f2d5b56826df85a Mon Sep 17 00:00:00 2001 +Date: Tue, 4 Jun 2024 19:09:40 +0800 +Subject: [PATCH] [Huawei]Keep objects when remove unshareable info +--- + hotspot/src/share/vm/oops/instanceKlass.cpp | 18 +++--------------- + .../Thread/TestThreadDumpClassInitMonitor.java | 15 +++++++++++---- + 2 files changed, 14 insertions(+), 19 deletions(-) + +diff --git a/hotspot/src/share/vm/oops/instanceKlass.cpp b/hotspot/src/share/vm/oops/instanceKlass.cpp +index 833cf9afe..df9aaabfb 100644 +--- a/hotspot/src/share/vm/oops/instanceKlass.cpp ++++ b/hotspot/src/share/vm/oops/instanceKlass.cpp +@@ -2467,21 +2467,6 @@ void InstanceKlass::remove_unshareable_info() { + m->remove_unshareable_info(); + } + +- if (UseAppCDS || DynamicDumpSharedSpaces) { +- if (_oop_map_cache != NULL) { +- delete _oop_map_cache; +- _oop_map_cache = NULL; +- } +- +- JNIid::deallocate(jni_ids()); +- set_jni_ids(NULL); +- +- jmethodID* jmeths = methods_jmethod_ids_acquire(); +- if (jmeths != (jmethodID*)NULL) { +- release_set_methods_jmethod_ids(NULL); +- FreeHeap(jmeths); +- } +- } + // do array classes also. + array_klasses_do(remove_unshareable_in_class); + // These are not allocated from metaspace. They are safe to set to NULL. +@@ -2489,6 +2474,9 @@ void InstanceKlass::remove_unshareable_info() { + _member_names = NULL; + _osr_nmethods_head = NULL; + _init_thread = NULL; ++ _oop_map_cache = NULL; ++ _jni_ids = NULL; ++ _methods_jmethod_ids = NULL; + } + + void InstanceKlass::remove_java_mirror() { +diff --git a/hotspot/test/runtime/Thread/TestThreadDumpClassInitMonitor.java b/hotspot/test/runtime/Thread/TestThreadDumpClassInitMonitor.java +index 8aa218efb..a2111c362 100644 +--- a/hotspot/test/runtime/Thread/TestThreadDumpClassInitMonitor.java ++++ b/hotspot/test/runtime/Thread/TestThreadDumpClassInitMonitor.java +@@ -148,34 +148,41 @@ public class TestThreadDumpClassInitMonitor { + throw new Error("Unexpected thread state line: " + line); + } + if (isProduct) { +- foundLines += 3; ++ foundLines += 4; + } else { + foundLines++; + } + continue; + } + case 2: { // Debug build ++ if (!line.trim().equals(JAVATHREAD_STATE)) { ++ throw new Error("Unexpected JavaThread state line: " + line); ++ } ++ foundLines++; ++ continue; ++ } ++ case 3: { // Debug build + if (!line.startsWith(THREAD_INFO)) { + throw new Error("Unexpected thread info line: " + line); + } + foundLines++; + continue; + } +- case 3: { // Debug build ++ case 4: { // Debug build + if (!line.trim().equals(JAVATHREAD_STATE)) { + throw new Error("Unexpected JavaThread state line: " + line); + } + foundLines++; + continue; + } +- case 4: { ++ case 5: { + if (!line.trim().startsWith(CURRENT_METHOD)) { + throw new Error("Unexpected current method line: " + line); + } + foundLines++; + continue; + } +- case 5: { ++ case 6: { + if (!line.trim().equals(WAIT_INFO)) { + throw new Error("Unexpected monitor information line: " + line); + } +-- +2.23.0 + diff --git a/Huawei-improve-GCTR-performance.patch b/Huawei-improve-GCTR-performance.patch new file mode 100644 index 0000000000000000000000000000000000000000..cbd1992ed09b1e753190af22e5d175bbd739f458 --- /dev/null +++ b/Huawei-improve-GCTR-performance.patch @@ -0,0 +1,62 @@ +From ac1502ff943911bd4d7332bd6531ed0a2454cf05 Mon Sep 17 00:00:00 2001 +Date: Mon, 27 May 2024 12:06:03 +0800 +Subject: [PATCH 2/2] improve GCTR performance +--- + .../classes/com/sun/crypto/provider/GCTR.java | 21 +++++++++++++++++-- + 1 file changed, 19 insertions(+), 2 deletions(-) + +diff --git a/jdk/src/share/classes/com/sun/crypto/provider/GCTR.java b/jdk/src/share/classes/com/sun/crypto/provider/GCTR.java +index 1ab0f63db..12af359b0 100644 +--- a/jdk/src/share/classes/com/sun/crypto/provider/GCTR.java ++++ b/jdk/src/share/classes/com/sun/crypto/provider/GCTR.java +@@ -29,6 +29,10 @@ + + package com.sun.crypto.provider; + ++import com.sun.management.HotSpotDiagnosticMXBean; ++import com.sun.management.VMOption; ++import sun.management.ManagementFactoryHelper; ++ + import java.nio.ByteBuffer; + import java.nio.ByteOrder; + import javax.crypto.IllegalBlockSizeException; +@@ -54,13 +58,26 @@ import static com.sun.crypto.provider.AESConstants.AES_BLOCK_SIZE; + */ + final class GCTR extends CounterMode { + ++ private static final String AES_CTR_INTRINSICS_PARAM = "UseAESCTRIntrinsics"; ++ private static boolean aesctrIntrinsicEnabled = false; ++ ++ static { ++ HotSpotDiagnosticMXBean diagnostic ++ = ManagementFactoryHelper.getDiagnosticMXBean(); ++ VMOption vmOption; ++ try { ++ vmOption = diagnostic.getVMOption(AES_CTR_INTRINSICS_PARAM); ++ } catch (IllegalArgumentException e) { ++ vmOption = null; ++ } ++ aesctrIntrinsicEnabled = Boolean.valueOf(vmOption == null ? null : vmOption.getValue()); ++ } + GCTR(SymmetricCipher cipher, byte[] initialCounterBlk) { + super(cipher); + if (initialCounterBlk.length != AES_BLOCK_SIZE) { + throw new RuntimeException("length of initial counter block (" + initialCounterBlk.length + + ") not equal to AES_BLOCK_SIZE (" + AES_BLOCK_SIZE + ")"); + } +- + iv = initialCounterBlk; + reset(); + } +@@ -93,7 +110,7 @@ final class GCTR extends CounterMode { + + long blocksLeft = blocksUntilRollover(); + int numOfCompleteBlocks = inLen / AES_BLOCK_SIZE; +- if (numOfCompleteBlocks >= blocksLeft) { ++ if (!aesctrIntrinsicEnabled || numOfCompleteBlocks >= blocksLeft) { + // Counter Mode encryption cannot be used because counter will + // roll over incorrectly. Use GCM-specific code instead. + byte[] encryptedCntr = new byte[AES_BLOCK_SIZE]; +-- +2.19.1 + diff --git a/add-safe-compilation-flags.patch b/add-safe-compilation-flags.patch index ccd57a663bffc015999a8ec329536871ffc64114..bf61aca88aea52986c7822813f650d9323c6f446 100644 --- a/add-safe-compilation-flags.patch +++ b/add-safe-compilation-flags.patch @@ -48,8 +48,8 @@ index f3581c163..a405eb336 100644 # improving the quality of crash log stack traces involving jvm.dll. # These are always used in all compiles --CXX_FLAGS=$(EXTRA_CFLAGS) /nologo /W3 /WX -+CXX_FLAGS=$(EXTRA_CFLAGS) /nologo /W3 /WX /GS +-CXX_FLAGS=$(EXTRA_CFLAGS) /nologo /W3 /WX /wd4800 ++CXX_FLAGS=$(EXTRA_CFLAGS) /nologo /W3 /WX /wd4800 /GS # Let's add debug information when Full Debug Symbols is enabled !if "$(ENABLE_FULL_DEBUG_SYMBOLS)" == "1" diff --git a/fix-log-bug-enhance-aes-hmac-performance.patch b/fix-log-bug-enhance-aes-hmac-performance.patch index c4110a17189c104a70107927ecc75b781e52fa47..a859556836293730380f8df8f4dea0a13aa9427d 100644 --- a/fix-log-bug-enhance-aes-hmac-performance.patch +++ b/fix-log-bug-enhance-aes-hmac-performance.patch @@ -149,7 +149,7 @@ index a405eb336..e5aed4418 100644 @@ -54,6 +54,9 @@ CXX=cl.exe # These are always used in all compiles - CXX_FLAGS=$(EXTRA_CFLAGS) /nologo /W3 /WX /GS + CXX_FLAGS=$(EXTRA_CFLAGS) /nologo /W3 /WX /wd4800 /GS +!if "$(MSC_VER)" > "1910" +CXX_FLAGS=$(EXTRA_CFLAGS) /nologo /W3 /GS /arch:IA32 +!endif diff --git a/fix_X509TrustManagerImpl_symantec_distrust.patch b/fix_X509TrustManagerImpl_symantec_distrust.patch index 65eeab574e11fab612e15f7535da3be6218528fa..777cba018c375417c2a84ce8dc20f495af652f24 100644 --- a/fix_X509TrustManagerImpl_symantec_distrust.patch +++ b/fix_X509TrustManagerImpl_symantec_distrust.patch @@ -40,13 +40,13 @@ index 54e1bfa0d..c1423dc5b 100644 // The numbers of certs now. - private static final int COUNT = 83; -+ private static final int COUNT = 102; ++ private static final int COUNT = 104; // SHA-256 of cacerts, can be generated with // shasum -a 256 cacerts | sed -e 's/../&:/g' | tr '[:lower:]' '[:upper:]' | cut -c1-95 private static final String CHECKSUM - = "2D:04:88:6C:52:53:54:EB:38:2D:BC:E0:AF:B7:82:F4:9E:32:A8:1A:1B:A3:AE:CF:25:CB:C2:F6:0F:4E:E1:20"; -+ = "2F:92:41:50:3B:2B:F2:AD:86:54:AB:2B:D4:AB:A2:92:8B:B6:1C:2B:58:A1:E3:1A:CE:43:43:FB:3E:94:2E:7E"; ++ = "1C:10:89:F9:32:8C:05:D1:10:90:27:7F:66:21:28:71:79:8F:55:44:6C:08:BA:00:48:C0:D4:7A:0D:3B:9C:45"; // map of cert alias to SHA-256 fingerprint @SuppressWarnings("serial") diff --git a/jdk8u-jdk8u412-b08.tar.xz b/jdk8u-jdk8u422-b05.tar.xz similarity index 82% rename from jdk8u-jdk8u412-b08.tar.xz rename to jdk8u-jdk8u422-b05.tar.xz index 41cfa2c9f1415ac1eb687d9ce7f4919ee9e95725..3fba88a6361cbf5235899dfc1b8713f5b489101a 100644 Binary files a/jdk8u-jdk8u412-b08.tar.xz and b/jdk8u-jdk8u422-b05.tar.xz differ diff --git a/openjdk-1.8.0.spec b/openjdk-1.8.0.spec index 7530afe0f2276f5dc2d26ff44dc6c6bdfce89239..9298a026d78b8e1c930fa5c157a4d13809dcafeb 100644 --- a/openjdk-1.8.0.spec +++ b/openjdk-1.8.0.spec @@ -172,13 +172,13 @@ %global origin_nice OpenJDK %global top_level_dir_name %{origin} %global repo jdk8u -%global revision jdk8u412-b08 +%global revision jdk8u422-b05 %global full_revision %{repo}-%{revision} # Define IcedTea version used for SystemTap tapsets and desktop files %global icedteaver 3.15.0 -%global updatever 412 -%global buildver b08 +%global updatever 422 +%global buildver b05 # priority must be 7 digits in total. The expression is workarounding tip %global priority 1800%{updatever} @@ -943,7 +943,7 @@ Provides: java-%{javaver}-%{origin}-accessibility%{?1} = %{epoch}:%{version}-%{r Name: java-%{javaver}-%{origin} Version: %{javaver}.%{updatever}.%{buildver} -Release: 9 +Release: 0 # java-1.5.0-ibm from jpackage.org set Epoch to 1 for unknown reasons # and this change was brought into RHEL-4. java-1.5.0-ibm packages # also included the epoch in their virtual provides. This created a @@ -1330,6 +1330,16 @@ Patch429: 8256488-Use-ldpq-stpq-instead-of-ld4-st4-for-small-c.patch Patch430: DependencyContext-mark_dependent_nmethods-crash-in-Dynamic-cds-mode.patch Patch431: 8138922-StubCodeDesc-constructor-publishes-partially-constructed.patch Patch432: support-KAE-zip.patch +Patch433: Backport-6956385-URLConnection.getLastModified-leaks-file-han.patch +Patch434: Backport-8068864-C2-failed-modified-node-is-not-on-IGVN._work.patch +Patch435: Huawei-improve-GCTR-performance.patch +Patch436: Backport-8209362-sun-security-ssl-SSLSocketImpl-ReuseAddr.jav.patch +Patch437: Backport-7036144-GZIPInputStream-readTrailer-uses-faulty-avai.patch +Patch438: Huawei-Add-Aggressive-CDS.patch +Patch439: Backport-8151845-Comment-in-globals.hpp-for-MetaspaceSize-is-.patch +Patch440: Backport-8210706-G1-may-deadlock-when-starting-a-concurrent-c.patch +Patch441: Backport-8318889-Backport-Important-Fixed-Issues-in-Later-Ver.patch +Patch442: Huawei-Keep-objects-when-remove-unshareable-info.patch ############################################# # # Upstreamable patches @@ -1975,6 +1985,16 @@ pushd %{top_level_dir_name} %patch430 -p1 %patch431 -p1 %patch432 -p1 +%patch433 -p1 +%patch434 -p1 +%patch435 -p1 +%patch436 -p1 +%patch437 -p1 +%patch438 -p1 +%patch439 -p1 +%patch440 -p1 +%patch441 -p1 +%patch442 -p1 %endif %ifarch loongarch64 @@ -2634,7 +2654,27 @@ cjc.mainProgram(args) -- the returns from copy_jdk_configs.lua should not affect %endif %changelog -* Thu Jul 4 2021 Autistic_boyya -1:1.8.0.412-b08.9 +* Thu Tue 16 2024 Autistic_boyya -1:1.8.0.422-b05.rolling +- modified 8014628-Support-AES-Encryption-with-HMAC-SHA2-for-Ke.patch +- modified 8136577_Make_AbortVMOnException_available_in_product_builds.patch +- modified Dynamic-CDS-Archive.patch +- modified add-safe-compilation-flags.patch +- modified fix-log-bug-enhance-aes-hmac-performance.patch +- modified fix_X509TrustManagerImpl_symantec_distrust.patch +- modified openjdk-1.8.0.spec +- modified update-cacerts-and-VerifyCACerts.java-test.patch +- Add Backport-6956385-URLConnection.getLastModified-leaks-file-han.patch +- Add Backport-7036144-GZIPInputStream-readTrailer-uses-faulty-avai.patch +- Add Backport-8068864-C2-failed-modified-node-is-not-on-IGVN._work.patch +- Add Backport-8151845-Comment-in-globals.hpp-for-MetaspaceSize-is-.patch +- Add Backport-8209362-sun-security-ssl-SSLSocketImpl-ReuseAddr.jav.patch +- Add Backport-8210706-G1-may-deadlock-when-starting-a-concurrent-c.patch +- Add Backport-8318889-Backport-Important-Fixed-Issues-in-Later-Ver.patch +- Add Huawei-Add-Aggressive-CDS.patch +- Add Huawei-Keep-objects-when-remove-unshareable-info.patch +- Add Huawei-improve-GCTR-performance.patch + +* Thu Jul 4 2024 Autistic_boyya -1:1.8.0.412-b08.9 - Add support-KAE-zip.patch * Fri Jun 21 2024 songliyang -1:1.8.0.412-b08.8 diff --git a/update-cacerts-and-VerifyCACerts.java-test.patch b/update-cacerts-and-VerifyCACerts.java-test.patch index 4128a07b63afd355bbe18e3a7cfd327cd31e7e86..3bcc6f44392f5b2669c39d87c37b3b43ebcd0dfc 100644 --- a/update-cacerts-and-VerifyCACerts.java-test.patch +++ b/update-cacerts-and-VerifyCACerts.java-test.patch @@ -257,13 +257,13 @@ index dd107fc..791ddb6 100644 + File.separator + "security" + File.separator + "cacerts"; // The numbers of certs now. -- private static final int COUNT = 108; +- private static final int COUNT = 110; + private static final int COUNT = 83; // SHA-256 of cacerts, can be generated with // shasum -a 256 cacerts | sed -e 's/../&:/g' | tr '[:lower:]' '[:upper:]' | cut -c1-95 private static final String CHECKSUM -- = "81:D4:84:F6:92:78:A4:82:25:06:DC:42:25:C9:5D:6C:63:E4:99:CE:BC:ED:66:B3:8C:BA:E6:BA:6B:34:0F:01"; +- = "C1:68:B4:AC:51:BF:B5:C6:FD:20:69:17:E1:AF:E4:5B:01:9B:AA:3F:C3:9A:80:A8:51:53:74:2C:A2:04:B0:FF"; + = "2D:04:88:6C:52:53:54:EB:38:2D:BC:E0:AF:B7:82:F4:9E:32:A8:1A:1B:A3:AE:CF:25:CB:C2:F6:0F:4E:E1:20"; // map of cert alias to SHA-256 fingerprint