diff --git a/make/devkit/createAutoconfBundle.sh b/make/devkit/createAutoconfBundle.sh
index 861a0a47242c0..7363b9cd8a71a 100644
--- a/make/devkit/createAutoconfBundle.sh
+++ b/make/devkit/createAutoconfBundle.sh
@@ -1,6 +1,6 @@
#!/bin/bash -e
#
-# Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2018, 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
@@ -25,50 +25,70 @@
#
# Create a bundle in the current directory, containing what's needed to run
-# the 'autoconf' program by the OpenJDK build.
+# the 'autoconf' program by the OpenJDK build. To override TARGET_PLATFORM
+# just set the variable before running this script.
# Autoconf depends on m4, so download and build that first.
AUTOCONF_VERSION=2.69
M4_VERSION=1.4.18
PACKAGE_VERSION=1.0.1
-TARGET_PLATFORM=linux_x86
+case `uname -s` in
+ Darwin)
+ os=macosx
+ ;;
+ Linux)
+ os=linux
+ ;;
+ CYGWIN*)
+ os=cygwin
+ ;;
+esac
+case `uname -m` in
+ arm64|aarch64)
+ arch=aarch64
+ ;;
+ amd64|x86_64|x64)
+ arch=x64
+ ;;
+esac
+TARGET_PLATFORM=${TARGET_PLATFORM:="${os}_${arch}"}
+
MODULE_NAME=autoconf-$TARGET_PLATFORM-$AUTOCONF_VERSION+$PACKAGE_VERSION
BUNDLE_NAME=$MODULE_NAME.tar.gz
-TMPDIR=`mktemp -d -t autoconfbundle-XXXX`
-trap "rm -rf \"$TMPDIR\"" EXIT
+SCRIPT_DIR="$(cd "$(dirname $0)" > /dev/null && pwd)"
+OUTPUT_ROOT="${SCRIPT_DIR}/../../build/autoconf"
-ORIG_DIR=`pwd`
-cd $TMPDIR
-OUTPUT_DIR=$TMPDIR/$MODULE_NAME
-mkdir -p $OUTPUT_DIR/usr
+cd $OUTPUT_ROOT
+IMAGE_DIR=$OUTPUT_ROOT/$MODULE_NAME
+mkdir -p $IMAGE_DIR/usr
# Download and build m4
if test "x$TARGET_PLATFORM" = xcygwin_x64; then
# On cygwin 64-bit, just copy the cygwin .exe file
- mkdir -p $OUTPUT_DIR/usr/bin
- cp /usr/bin/m4 $OUTPUT_DIR/usr/bin
+ mkdir -p $IMAGE_DIR/usr/bin
+ cp /usr/bin/m4 $IMAGE_DIR/usr/bin
elif test "x$TARGET_PLATFORM" = xcygwin_x86; then
# On cygwin 32-bit, just copy the cygwin .exe file
- mkdir -p $OUTPUT_DIR/usr/bin
- cp /usr/bin/m4 $OUTPUT_DIR/usr/bin
+ mkdir -p $IMAGE_DIR/usr/bin
+ cp /usr/bin/m4 $IMAGE_DIR/usr/bin
elif test "x$TARGET_PLATFORM" = xlinux_x64; then
M4_VERSION=1.4.13-5
wget http://yum.oracle.com/repo/OracleLinux/OL6/latest/x86_64/getPackage/m4-$M4_VERSION.el6.x86_64.rpm
- cd $OUTPUT_DIR
- rpm2cpio ../m4-$M4_VERSION.el6.x86_64.rpm | cpio -d -i
+ cd $IMAGE_DIR
+ rpm2cpio $OUTPUT_ROOT/m4-$M4_VERSION.el6.x86_64.rpm | cpio -d -i
elif test "x$TARGET_PLATFORM" = xlinux_x86; then
M4_VERSION=1.4.13-5
wget http://yum.oracle.com/repo/OracleLinux/OL6/latest/i386/getPackage/m4-$M4_VERSION.el6.i686.rpm
- cd $OUTPUT_DIR
- rpm2cpio ../m4-$M4_VERSION.el6.i686.rpm | cpio -d -i
+ cd $IMAGE_DIR
+ rpm2cpio $OUTPUT_ROOT/m4-$M4_VERSION.el6.i686.rpm | cpio -d -i
else
wget https://ftp.gnu.org/gnu/m4/m4-$M4_VERSION.tar.gz
tar xzf m4-$M4_VERSION.tar.gz
cd m4-$M4_VERSION
- ./configure --prefix=$OUTPUT_DIR/usr
+ ./configure --prefix=$IMAGE_DIR/usr CFLAGS="-w -Wno-everything"
make
make install
cd ..
@@ -79,15 +99,14 @@ fi
wget https://ftp.gnu.org/gnu/autoconf/autoconf-$AUTOCONF_VERSION.tar.gz
tar xzf autoconf-$AUTOCONF_VERSION.tar.gz
cd autoconf-$AUTOCONF_VERSION
-./configure --prefix=$OUTPUT_DIR/usr M4=$OUTPUT_DIR/usr/bin/m4
+./configure --prefix=$IMAGE_DIR/usr M4=$IMAGE_DIR/usr/bin/m4
make
make install
cd ..
-perl -pi -e "s!$OUTPUT_DIR/!./!" $OUTPUT_DIR/usr/bin/auto* $OUTPUT_DIR/usr/share/autoconf/autom4te.cfg
-cp $OUTPUT_DIR/usr/share/autoconf/autom4te.cfg $OUTPUT_DIR/autom4te.cfg
+perl -pi -e "s!$IMAGE_DIR/!./!" $IMAGE_DIR/usr/bin/auto* $IMAGE_DIR/usr/share/autoconf/autom4te.cfg
-cat > $OUTPUT_DIR/autoconf << EOF
+cat > $IMAGE_DIR/autoconf << EOF
#!/bin/bash
# Get an absolute path to this script
this_script_dir=\`dirname \$0\`
@@ -100,17 +119,10 @@ export AUTOHEADER="\$this_script_dir/usr/bin/autoheader"
export AC_MACRODIR="\$this_script_dir/usr/share/autoconf"
export autom4te_perllibdir="\$this_script_dir/usr/share/autoconf"
-autom4te_cfg=\$this_script_dir/usr/share/autoconf/autom4te.cfg
-cp \$this_script_dir/autom4te.cfg \$autom4te_cfg
-
-echo 'begin-language: "M4sugar"' >> \$autom4te_cfg
-echo "args: --prepend-include '"\$this_script_dir/usr/share/autoconf"'" >> \$autom4te_cfg
-echo 'end-language: "M4sugar"' >> \$autom4te_cfg
+PREPEND_INCLUDE="--prepend-include \$this_script_dir/usr/share/autoconf"
-exec \$this_script_dir/usr/bin/autoconf "\$@"
+exec \$this_script_dir/usr/bin/autoconf \$PREPEND_INCLUDE "\$@"
EOF
-chmod +x $OUTPUT_DIR/autoconf
-cd $OUTPUT_DIR
-tar -cvzf ../$BUNDLE_NAME *
-cd ..
-cp $BUNDLE_NAME "$ORIG_DIR"
+chmod +x $IMAGE_DIR/autoconf
+cd $IMAGE_DIR
+tar -cvzf $OUTPUT_ROOT/$BUNDLE_NAME *
diff --git a/make/test/JtregNativeHotspot.gmk b/make/test/JtregNativeHotspot.gmk
index 8916eee90d7bc..97f2f12cb7639 100644
--- a/make/test/JtregNativeHotspot.gmk
+++ b/make/test/JtregNativeHotspot.gmk
@@ -885,7 +885,7 @@ BUILD_HOTSPOT_JTREG_EXECUTABLES_JDK_LIBS_exedaemonDestroy := java.base:libjvm
ifeq ($(call isTargetOs, windows), true)
BUILD_HOTSPOT_JTREG_EXECUTABLES_CFLAGS_exeFPRegs := -MT
- BUILD_HOTSPOT_JTREG_EXCLUDE += exesigtest.c libterminatedThread.c libTestJNI.c libCompleteExit.c libMonitorWithDeadObjectTest.c libTestPsig.c exeGetCreatedJavaVMs.c
+ BUILD_HOTSPOT_JTREG_EXCLUDE += exesigtest.c libterminatedThread.c libTestJNI.c libCompleteExit.c libMonitorWithDeadObjectTest.c libTestPsig.c exeGetCreatedJavaVMs.c libTestUnloadedClass.cpp
BUILD_HOTSPOT_JTREG_LIBRARIES_JDK_LIBS_libnativeStack := java.base:libjvm
BUILD_HOTSPOT_JTREG_LIBRARIES_JDK_LIBS_libVThreadEventTest := java.base:libjvm
else
@@ -1526,6 +1526,7 @@ else
BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libCompleteExit += -lpthread
BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libMonitorWithDeadObjectTest += -lpthread
BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libnativeStack += -lpthread
+ BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libTestUnloadedClass += -lpthread
BUILD_HOTSPOT_JTREG_LIBRARIES_JDK_LIBS_libVThreadEventTest := java.base:libjvm
BUILD_HOTSPOT_JTREG_EXECUTABLES_LIBS_exeGetCreatedJavaVMs := -lpthread
BUILD_HOTSPOT_JTREG_EXECUTABLES_JDK_LIBS_exeGetCreatedJavaVMs := java.base:libjvm
diff --git a/src/hotspot/share/classfile/classLoaderExt.cpp b/src/hotspot/share/classfile/classLoaderExt.cpp
index 78e29f990d7d1..3cd7dd7cd3ba6 100644
--- a/src/hotspot/share/classfile/classLoaderExt.cpp
+++ b/src/hotspot/share/classfile/classLoaderExt.cpp
@@ -213,6 +213,15 @@ void ClassLoaderExt::process_jar_manifest(JavaThread* current, ClassPathEntry* e
char sep = os::file_separator()[0];
const char* dir_name = entry->name();
const char* dir_tail = strrchr(dir_name, sep);
+#ifdef _WINDOWS
+ // On Windows, we also support forward slash as the file separator when locating entries in the classpath entry.
+ const char* dir_tail2 = strrchr(dir_name, '/');
+ if (dir_tail == nullptr) {
+ dir_tail = dir_tail2;
+ } else if (dir_tail2 != nullptr && dir_tail2 > dir_tail) {
+ dir_tail = dir_tail2;
+ }
+#endif
int dir_len;
if (dir_tail == nullptr) {
dir_len = 0;
diff --git a/src/hotspot/share/prims/jvmtiEnv.cpp b/src/hotspot/share/prims/jvmtiEnv.cpp
index a36d12059a96a..097ce33154051 100644
--- a/src/hotspot/share/prims/jvmtiEnv.cpp
+++ b/src/hotspot/share/prims/jvmtiEnv.cpp
@@ -3132,7 +3132,9 @@ JvmtiEnv::GetFieldName(fieldDescriptor* fdesc_ptr, char** name_ptr, char** signa
// declaring_class_ptr - pre-checked for null
jvmtiError
JvmtiEnv::GetFieldDeclaringClass(fieldDescriptor* fdesc_ptr, jclass* declaring_class_ptr) {
-
+ // As for the GetFieldDeclaringClass method, the XSL generated C++ code that calls it has
+ // a jclass of the relevant class or a subclass of it, which is fine in terms of ensuring
+ // the holder is kept alive.
*declaring_class_ptr = get_jni_class_non_null(fdesc_ptr->field_holder());
return JVMTI_ERROR_NONE;
} /* end GetFieldDeclaringClass */
@@ -3210,7 +3212,9 @@ JvmtiEnv::GetMethodName(Method* method, char** name_ptr, char** signature_ptr, c
jvmtiError
JvmtiEnv::GetMethodDeclaringClass(Method* method, jclass* declaring_class_ptr) {
NULL_CHECK(method, JVMTI_ERROR_INVALID_METHODID);
- (*declaring_class_ptr) = get_jni_class_non_null(method->method_holder());
+ Klass* k = method->method_holder();
+ Handle holder(Thread::current(), k->klass_holder()); // keep the klass alive
+ (*declaring_class_ptr) = get_jni_class_non_null(k);
return JVMTI_ERROR_NONE;
} /* end GetMethodDeclaringClass */
diff --git a/src/hotspot/share/prims/jvmtiEnvBase.cpp b/src/hotspot/share/prims/jvmtiEnvBase.cpp
index a05d69980931c..167ca557cde31 100644
--- a/src/hotspot/share/prims/jvmtiEnvBase.cpp
+++ b/src/hotspot/share/prims/jvmtiEnvBase.cpp
@@ -599,6 +599,7 @@ JvmtiEnvBase::jvf_for_thread_and_depth(JavaThread* java_thread, jint depth) {
jclass
JvmtiEnvBase::get_jni_class_non_null(Klass* k) {
assert(k != nullptr, "k != null");
+ assert(k->is_loader_alive(), "Must be alive");
Thread *thread = Thread::current();
return (jclass)jni_reference(Handle(thread, k->java_mirror()));
}
diff --git a/src/java.base/share/classes/java/io/ObjectInputFilter.java b/src/java.base/share/classes/java/io/ObjectInputFilter.java
index e40a24072060d..879820761c129 100644
--- a/src/java.base/share/classes/java/io/ObjectInputFilter.java
+++ b/src/java.base/share/classes/java/io/ObjectInputFilter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -1218,8 +1218,7 @@ private static boolean matchesPackage(Class> c, String pkg) {
}
/**
- * Returns the pattern used to create this filter.
- * @return the pattern used to create this filter
+ * {@return the pattern used to create this filter}
*/
@Override
public String toString() {
diff --git a/src/java.base/share/classes/java/io/ObjectInputStream.java b/src/java.base/share/classes/java/io/ObjectInputStream.java
index 74c34d80a7beb..983b80d2bc673 100644
--- a/src/java.base/share/classes/java/io/ObjectInputStream.java
+++ b/src/java.base/share/classes/java/io/ObjectInputStream.java
@@ -3859,8 +3859,7 @@ private int readUTFChar(StringBuilder sbuf, long utflen)
}
/**
- * Returns the number of bytes read from the input stream.
- * @return the number of bytes read from the input stream
+ * {@return the number of bytes read from the input stream}
*/
long getBytesRead() {
return in.getBytesRead();
diff --git a/src/java.base/share/classes/java/lang/annotation/Retention.java b/src/java.base/share/classes/java/lang/annotation/Retention.java
index daf5f6e9b23d3..a8afc76ac79f7 100644
--- a/src/java.base/share/classes/java/lang/annotation/Retention.java
+++ b/src/java.base/share/classes/java/lang/annotation/Retention.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -45,8 +45,7 @@
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
/**
- * Returns the retention policy.
- * @return the retention policy
+ * {@return the retention policy}
*/
RetentionPolicy value();
}
diff --git a/src/java.base/share/classes/java/lang/foreign/MemorySegment.java b/src/java.base/share/classes/java/lang/foreign/MemorySegment.java
index cb1f3707db68c..9fadc2f0f56d1 100644
--- a/src/java.base/share/classes/java/lang/foreign/MemorySegment.java
+++ b/src/java.base/share/classes/java/lang/foreign/MemorySegment.java
@@ -1285,6 +1285,14 @@ MemorySegment reinterpret(long newSize,
* sequences with this charset's default replacement string. The {@link
* java.nio.charset.CharsetDecoder} class should be used when more control
* over the decoding process is required.
+ *
+ * Getting a string from a segment with a known byte offset and
+ * known byte length can be done like so:
+ * {@snippet lang=java :
+ * byte[] bytes = new byte[length];
+ * MemorySegment.copy(segment, JAVA_BYTE, offset, bytes, 0, length);
+ * return new String(bytes, charset);
+ * }
*
* @param offset offset in bytes (relative to this segment address) at which this
* access operation will occur
diff --git a/src/java.base/share/classes/java/nio/charset/MalformedInputException.java b/src/java.base/share/classes/java/nio/charset/MalformedInputException.java
index 37e20040dd554..c36f81f9153d9 100644
--- a/src/java.base/share/classes/java/nio/charset/MalformedInputException.java
+++ b/src/java.base/share/classes/java/nio/charset/MalformedInputException.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -56,16 +56,14 @@ public MalformedInputException(int inputLength) {
}
/**
- * Returns the length of the input.
- * @return the length of the input
+ * {@return the length of the input}
*/
public int getInputLength() {
return inputLength;
}
/**
- * Returns the message.
- * @return the message
+ * {@return the message}
*/
public String getMessage() {
return "Input length = " + inputLength;
diff --git a/src/java.base/share/classes/java/nio/charset/UnmappableCharacterException.java b/src/java.base/share/classes/java/nio/charset/UnmappableCharacterException.java
index c5fddd1684fd1..857c519974d7c 100644
--- a/src/java.base/share/classes/java/nio/charset/UnmappableCharacterException.java
+++ b/src/java.base/share/classes/java/nio/charset/UnmappableCharacterException.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -56,16 +56,14 @@ public UnmappableCharacterException(int inputLength) {
}
/**
- * Returns the length of the input.
- * @return the length of the input
+ * {@return the length of the input}
*/
public int getInputLength() {
return inputLength;
}
/**
- * Returns the message.
- * @return the message
+ * {@return the message}
*/
public String getMessage() {
return "Input length = " + inputLength;
diff --git a/src/java.base/share/classes/java/time/format/TextStyle.java b/src/java.base/share/classes/java/time/format/TextStyle.java
index ec49da271adc7..2a1f8b896cab4 100644
--- a/src/java.base/share/classes/java/time/format/TextStyle.java
+++ b/src/java.base/share/classes/java/time/format/TextStyle.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -137,8 +137,7 @@ public boolean isStandalone() {
}
/**
- * Returns the stand-alone style with the same size.
- * @return the stand-alone style with the same size
+ * {@return the stand-alone style with the same size}
*/
public TextStyle asStandalone() {
return TextStyle.values()[ordinal() | 1];
diff --git a/src/java.base/share/classes/java/util/SplittableRandom.java b/src/java.base/share/classes/java/util/SplittableRandom.java
index cb1801f56805d..686fe66da2f53 100644
--- a/src/java.base/share/classes/java/util/SplittableRandom.java
+++ b/src/java.base/share/classes/java/util/SplittableRandom.java
@@ -47,7 +47,7 @@
*
Series of generated values pass the DieHarder suite testing
* independence and uniformity properties of random number generators.
* (Most recently validated with version
+ * href="https://webhome.phy.duke.edu/~rgb/General/dieharder.php"> version
* 3.31.1.) These tests validate only the methods for certain
* types and ranges, but similar properties are expected to hold, at
* least approximately, for others as well. The period
diff --git a/src/java.base/share/classes/java/util/concurrent/SynchronousQueue.java b/src/java.base/share/classes/java/util/concurrent/SynchronousQueue.java
index 6d6d9efad0398..f5a2ce4d9b4cc 100644
--- a/src/java.base/share/classes/java/util/concurrent/SynchronousQueue.java
+++ b/src/java.base/share/classes/java/util/concurrent/SynchronousQueue.java
@@ -477,8 +477,7 @@ public Spliterator spliterator() {
}
/**
- * Returns a zero-length array.
- * @return a zero-length array
+ * {@return a zero-length array}
*/
public Object[] toArray() {
return new Object[0];
diff --git a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicBoolean.java b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicBoolean.java
index d8cb9869afecd..c6671deaa2eb5 100644
--- a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicBoolean.java
+++ b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicBoolean.java
@@ -176,8 +176,7 @@ public final boolean getAndSet(boolean newValue) {
}
/**
- * Returns the String representation of the current value.
- * @return the String representation of the current value
+ * {@return the String representation of the current value}
*/
public String toString() {
return Boolean.toString(get());
diff --git a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicInteger.java b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicInteger.java
index 4f08ed3f64b68..4ebd758ccc7a3 100644
--- a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicInteger.java
+++ b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicInteger.java
@@ -340,8 +340,7 @@ public final int accumulateAndGet(int x,
}
/**
- * Returns the String representation of the current value.
- * @return the String representation of the current value
+ * {@return the String representation of the current value}
*/
public String toString() {
return Integer.toString(get());
diff --git a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerArray.java b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerArray.java
index 676788e4204ab..7e253ead3354f 100644
--- a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerArray.java
+++ b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerArray.java
@@ -366,8 +366,7 @@ public final int accumulateAndGet(int i, int x,
}
/**
- * Returns the String representation of the current values of array.
- * @return the String representation of the current values of array
+ * {@return the String representation of the current values of array}
*/
public String toString() {
int iMax = array.length - 1;
diff --git a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLong.java b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLong.java
index e446df8fd3e0c..d0e50b0fda885 100644
--- a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLong.java
+++ b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLong.java
@@ -341,8 +341,7 @@ public final long accumulateAndGet(long x,
}
/**
- * Returns the String representation of the current value.
- * @return the String representation of the current value
+ * {@return the String representation of the current value}
*/
public String toString() {
return Long.toString(get());
diff --git a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongArray.java b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongArray.java
index af2ff6729fd77..2145c79579971 100644
--- a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongArray.java
+++ b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongArray.java
@@ -366,8 +366,7 @@ public final long accumulateAndGet(int i, long x,
}
/**
- * Returns the String representation of the current values of array.
- * @return the String representation of the current values of array
+ * {@return the String representation of the current values of array}
*/
public String toString() {
int iMax = array.length - 1;
diff --git a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReference.java b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReference.java
index b2c692df5e7c7..da445da61badc 100644
--- a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReference.java
+++ b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReference.java
@@ -269,8 +269,7 @@ public final V accumulateAndGet(V x,
}
/**
- * Returns the String representation of the current value.
- * @return the String representation of the current value
+ * {@return the String representation of the current value}
*/
public String toString() {
return String.valueOf(get());
diff --git a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java
index f85fb9376ad93..e8238320e2179 100644
--- a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java
+++ b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java
@@ -297,8 +297,7 @@ public final E accumulateAndGet(int i, E x,
}
/**
- * Returns the String representation of the current values of array.
- * @return the String representation of the current values of array
+ * {@return the String representation of the current values of array}
*/
public String toString() {
int iMax = array.length - 1;
diff --git a/src/java.base/share/classes/java/util/concurrent/atomic/DoubleAccumulator.java b/src/java.base/share/classes/java/util/concurrent/atomic/DoubleAccumulator.java
index d04b8253ee76d..eb837a0fd29ad 100644
--- a/src/java.base/share/classes/java/util/concurrent/atomic/DoubleAccumulator.java
+++ b/src/java.base/share/classes/java/util/concurrent/atomic/DoubleAccumulator.java
@@ -189,8 +189,7 @@ public double getThenReset() {
}
/**
- * Returns the String representation of the current value.
- * @return the String representation of the current value
+ * {@return the String representation of the current value}
*/
public String toString() {
return Double.toString(get());
diff --git a/src/java.base/share/classes/java/util/concurrent/atomic/LongAccumulator.java b/src/java.base/share/classes/java/util/concurrent/atomic/LongAccumulator.java
index be96853ce0921..0d48a686cf2a1 100644
--- a/src/java.base/share/classes/java/util/concurrent/atomic/LongAccumulator.java
+++ b/src/java.base/share/classes/java/util/concurrent/atomic/LongAccumulator.java
@@ -183,8 +183,7 @@ public long getThenReset() {
}
/**
- * Returns the String representation of the current value.
- * @return the String representation of the current value
+ * {@return the String representation of the current value}
*/
public String toString() {
return Long.toString(get());
diff --git a/src/java.base/share/classes/java/util/jar/Manifest.java b/src/java.base/share/classes/java/util/jar/Manifest.java
index c0e30707a35ee..d584503329336 100644
--- a/src/java.base/share/classes/java/util/jar/Manifest.java
+++ b/src/java.base/share/classes/java/util/jar/Manifest.java
@@ -119,8 +119,7 @@ public Manifest(Manifest man) {
}
/**
- * Returns the main Attributes for the Manifest.
- * @return the main Attributes for the Manifest
+ * {@return the main Attributes for the Manifest}
*/
public Attributes getMainAttributes() {
return attr;
diff --git a/src/java.base/share/classes/java/util/zip/Deflater.java b/src/java.base/share/classes/java/util/zip/Deflater.java
index 56d0978dbc00d..a23f8395c2178 100644
--- a/src/java.base/share/classes/java/util/zip/Deflater.java
+++ b/src/java.base/share/classes/java/util/zip/Deflater.java
@@ -782,8 +782,7 @@ public int deflate(ByteBuffer output, int flush) {
}
/**
- * Returns the ADLER-32 value of the uncompressed data.
- * @return the ADLER-32 value of the uncompressed data
+ * {@return the ADLER-32 value of the uncompressed data}
*/
public int getAdler() {
synchronized (zsRef) {
diff --git a/src/java.base/share/classes/java/util/zip/Inflater.java b/src/java.base/share/classes/java/util/zip/Inflater.java
index 22ab21d88c0b0..109208bd9ad8c 100644
--- a/src/java.base/share/classes/java/util/zip/Inflater.java
+++ b/src/java.base/share/classes/java/util/zip/Inflater.java
@@ -282,8 +282,7 @@ public boolean needsInput() {
}
/**
- * Returns true if a preset dictionary is needed for decompression.
- * @return true if a preset dictionary is needed for decompression
+ * {@return true if a preset dictionary is needed for decompression}
* @see Inflater#setDictionary
*/
public boolean needsDictionary() {
@@ -293,10 +292,8 @@ public boolean needsDictionary() {
}
/**
- * Returns true if the end of the compressed data stream has been
- * reached.
- * @return true if the end of the compressed data stream has been
- * reached
+ * {@return true if the end of the compressed data stream has been
+ * reached}
*/
public boolean finished() {
synchronized (zsRef) {
@@ -602,8 +599,7 @@ public int inflate(ByteBuffer output) throws DataFormatException {
}
/**
- * Returns the ADLER-32 value of the uncompressed data.
- * @return the ADLER-32 value of the uncompressed data
+ * {@return the ADLER-32 value of the uncompressed data}
*/
public int getAdler() {
synchronized (zsRef) {
diff --git a/src/java.base/share/classes/java/util/zip/ZipEntry.java b/src/java.base/share/classes/java/util/zip/ZipEntry.java
index d97760d950ab3..8c8bfeb322960 100644
--- a/src/java.base/share/classes/java/util/zip/ZipEntry.java
+++ b/src/java.base/share/classes/java/util/zip/ZipEntry.java
@@ -138,8 +138,7 @@ public ZipEntry(ZipEntry e) {
}
/**
- * Returns the name of the entry.
- * @return the name of the entry
+ * {@return the name of the entry}
*/
public String getName() {
return name;
diff --git a/src/java.base/share/classes/java/util/zip/ZipFile.java b/src/java.base/share/classes/java/util/zip/ZipFile.java
index 80126bc79734d..333e3d0184976 100644
--- a/src/java.base/share/classes/java/util/zip/ZipFile.java
+++ b/src/java.base/share/classes/java/util/zip/ZipFile.java
@@ -498,8 +498,7 @@ public int available() throws IOException {
}
/**
- * Returns the path name of the ZIP file.
- * @return the path name of the ZIP file
+ * {@return the path name of the ZIP file}
*/
public String getName() {
return filePath;
@@ -560,8 +559,7 @@ public Iterator asIterator() {
}
/**
- * Returns an enumeration of the ZIP file entries.
- * @return an enumeration of the ZIP file entries
+ * {@return an enumeration of the ZIP file entries}
* @throws IllegalStateException if the ZIP file has been closed
*/
public Enumeration extends ZipEntry> entries() {
diff --git a/src/java.base/share/classes/jdk/internal/foreign/SegmentBulkOperations.java b/src/java.base/share/classes/jdk/internal/foreign/SegmentBulkOperations.java
index 41ae247293d3f..30e146a82f49b 100644
--- a/src/java.base/share/classes/jdk/internal/foreign/SegmentBulkOperations.java
+++ b/src/java.base/share/classes/jdk/internal/foreign/SegmentBulkOperations.java
@@ -207,15 +207,6 @@ private static long mismatch(AbstractMemorySegmentImpl src, long srcFromOffset,
}
}
int remaining = length - offset;
- // 0...XXX000
- for (; remaining >= 8; remaining -= 8) {
- final long s = SCOPED_MEMORY_ACCESS.getLongUnaligned(src.sessionImpl(), src.unsafeGetBase(), src.unsafeGetOffset() + srcFromOffset + offset, !Architecture.isLittleEndian());
- final long d = SCOPED_MEMORY_ACCESS.getLongUnaligned(dst.sessionImpl(), dst.unsafeGetBase(), dst.unsafeGetOffset() + dstFromOffset + offset, !Architecture.isLittleEndian());
- if (s != d) {
- return start + offset + mismatch(s, d);
- }
- offset += 8;
- }
// 0...0X00
if (remaining >= 4) {
diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SunPKCS11.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SunPKCS11.java
index 4d10584fa09ba..44a2c4efb0694 100644
--- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SunPKCS11.java
+++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SunPKCS11.java
@@ -27,7 +27,7 @@
import java.io.*;
import java.util.*;
-
+import java.util.stream.Collectors;
import java.security.*;
import java.security.interfaces.*;
@@ -1272,7 +1272,11 @@ private void initToken(CK_SLOT_INFO slotInfo) throws PKCS11Exception {
CKM_SHA3_512_RSA_PKCS_PSS);
}
}
+
long[] supportedMechanisms = p11.C_GetMechanismList(slotID);
+ Set supportedMechSet =
+ Arrays.stream(supportedMechanisms).boxed().collect
+ (Collectors.toCollection(HashSet::new));
// Create a map from the various Descriptors to the "most
// preferred" mechanism that was defined during the
@@ -1281,10 +1285,9 @@ private void initToken(CK_SLOT_INFO slotInfo) throws PKCS11Exception {
// the earliest entry. When asked for "DES/CBC/PKCS5Padding", we
// return a CKM_DES_CBC_PAD.
final Map supportedAlgs =
- new HashMap();
+ new HashMap();
- for (int i = 0; i < supportedMechanisms.length; i++) {
- long longMech = supportedMechanisms[i];
+ for (long longMech : supportedMechanisms) {
CK_MECHANISM_INFO mechInfo = token.getMechanismInfo(longMech);
if (showInfo) {
System.out.println("Mechanism " +
@@ -1331,13 +1334,19 @@ private void initToken(CK_SLOT_INFO slotInfo) throws PKCS11Exception {
for (Descriptor d : ds) {
Integer oldMech = supportedAlgs.get(d);
if (oldMech == null) {
+ // check all required mechs are supported
if (d.requiredMechs != null) {
- // Check that other mechanisms required for the
- // service are supported before listing it as
- // available for the first time.
- for (int requiredMech : d.requiredMechs) {
- if (token.getMechanismInfo(
- requiredMech & 0xFFFFFFFFL) == null) {
+ for (int reqMech : d.requiredMechs) {
+ long longReqMech = reqMech & 0xFFFFFFFFL;
+ if (!config.isEnabled(longReqMech) ||
+ !supportedMechSet.contains(longReqMech) ||
+ brokenMechanisms.contains(longReqMech)) {
+ if (showInfo) {
+ System.out.println("DISABLED " + d.type +
+ " " + d.algorithm +
+ " due to no support for req'd mech " +
+ Functions.getMechanismName(longReqMech));
+ }
continue descLoop;
}
}
@@ -1350,7 +1359,7 @@ private void initToken(CK_SLOT_INFO slotInfo) throws PKCS11Exception {
(d.type == SIG &&
(mechInfo.flags & CKF_SIGN) == 0)) {
if (showInfo) {
- System.out.println("DISABLED " + d.type +
+ System.out.println("DISABLED " + d.type +
" " + d.algorithm +
" due to partial support");
}
@@ -1374,7 +1383,6 @@ private void initToken(CK_SLOT_INFO slotInfo) throws PKCS11Exception {
}
}
}
-
}
// register algorithms in provider
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/ClassPathAttr.java b/test/hotspot/jtreg/runtime/cds/appcds/ClassPathAttr.java
index f0d797c09aedf..560f42d0467da 100644
--- a/test/hotspot/jtreg/runtime/cds/appcds/ClassPathAttr.java
+++ b/test/hotspot/jtreg/runtime/cds/appcds/ClassPathAttr.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -30,6 +30,7 @@
* @run driver/timeout=240 ClassPathAttr
*/
+import jdk.test.lib.Platform;
import jdk.test.lib.cds.CDSTestUtils;
import jdk.test.lib.process.OutputAnalyzer;
import java.io.File;
@@ -82,6 +83,76 @@ static void testNormalOps() throws Exception {
output.shouldMatch("checking shared classpath entry: .*cpattr2.jar");
output.shouldMatch("checking shared classpath entry: .*cpattr3.jar");
});
+
+ // Test handling of forward slash ('/') file separator when locating entries
+ // in the classpath entry on Windows.
+ // Skip the following test when CDS dynamic dump is enabled due to some
+ // issue when converting a relative path to real path.
+ if (Platform.isWindows() && !CDSTestUtils.DYNAMIC_DUMP) {
+ // Test with relative path
+ // Find the index to the dir before the jar file.
+ int idx = jar1.lastIndexOf(File.separator);
+ idx = jar1.substring(0, idx - 1).lastIndexOf(File.separator);
+ // Setup jar directory and names.
+ String jarDir = jar1.substring(0, idx);
+ String jar1Name = jar1.substring(idx + 1);
+ String jar4Name = jar4.substring(idx + 1);
+ String newCp = jar1Name.replace("\\", "/") + File.pathSeparator + jar4Name.replace("\\", "/");
+
+ OutputAnalyzer out = TestCommon.testDump(jarDir, newCp, classlist, "-Xlog:class+path=info");
+ if (i == 1) {
+ out.shouldMatch("opened:.*cpattr1.jar"); // first jar on -cp
+ } else {
+ // first jar on -cp with long Class-Path: attribute
+ out.shouldMatch("opened:.*cpattr1_long.jar");
+ }
+ // one of the jar in the Class-Path: attribute of cpattr1.jar
+ out.shouldMatch("opened:.*cpattr2.jar");
+
+ TestCommon.runWithRelativePath(
+ jarDir.replace("\\", "/"),
+ "-Xlog:class+path,class+load",
+ "-cp", newCp,
+ "CpAttr1")
+ .assertNormalExit(output -> {
+ output.shouldMatch("checking shared classpath entry: .*cpattr2.jar");
+ output.shouldMatch("checking shared classpath entry: .*cpattr3.jar");
+ });
+
+ // Go one directory up.
+ int idx2 = jar1.substring(0, idx - 1).lastIndexOf(File.separator);
+ if (idx2 != -1) {
+ // Setup jar directory and names.
+ jarDir = jar1.substring(0, idx2);
+ // Set relative path to jar containing '\' and '/' file separators
+ // e.g. d1\d2/A.jar
+ jar1Name = jar1.substring(idx2 + 1).replace("\\", "/");
+ jar4Name = jar4.substring(idx2 + 1).replace("\\", "/");
+ jar1Name = jar1Name.replaceFirst("/", "\\\\");
+ jar4Name = jar4Name.replaceFirst("/", "\\\\");
+
+ newCp = jar1Name + File.pathSeparator + jar4Name;
+ out = TestCommon.testDump(jarDir, newCp, classlist, "-Xlog:class+path=info");
+ if (i == 1) {
+ out.shouldMatch("opened:.*cpattr1.jar"); // first jar on -cp
+ } else {
+ // first jar on -cp with long Class-Path: attribute
+ out.shouldMatch("opened:.*cpattr1_long.jar");
+ }
+ // one of the jar in the Class-Path: attribute of cpattr1.jar
+ out.shouldMatch("opened:.*cpattr2.jar");
+
+ TestCommon.runWithRelativePath(
+ jarDir.replace("\\", "/"),
+ "-Xlog:class+path,class+load",
+ "-cp", newCp,
+ "CpAttr1")
+ .assertNormalExit(output -> {
+ output.shouldMatch("checking shared classpath entry: .*cpattr2.jar");
+ output.shouldMatch("checking shared classpath entry: .*cpattr3.jar");
+ });
+ }
+ }
}
// test duplicate jars in the "Class-path" attribute in the jar manifest
diff --git a/test/hotspot/jtreg/serviceability/jvmti/GetMethodDeclaringClass/TestUnloadedClass.java b/test/hotspot/jtreg/serviceability/jvmti/GetMethodDeclaringClass/TestUnloadedClass.java
new file mode 100644
index 0000000000000..dafec97111e2f
--- /dev/null
+++ b/test/hotspot/jtreg/serviceability/jvmti/GetMethodDeclaringClass/TestUnloadedClass.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
+ * Copyright (c) 2024, Alibaba Group Holding Limited. 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 8339725
+ * @summary Stress test GetMethodDeclaringClass
+ * @requires vm.jvmti
+ * @requires (os.family == "linux")
+ * @library /test/lib
+ * @run driver/timeout=300 TestUnloadedClass
+ */
+
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.Utils;
+import jdk.test.lib.process.ProcessTools;
+import jdk.test.lib.Platform;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.InputStream;
+import java.lang.reflect.Constructor;
+
+public class TestUnloadedClass {
+ public static void main(String[] args) throws Exception {
+ ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder(
+ "-agentpath:" + Utils.TEST_NATIVE_PATH + File.separator + System.mapLibraryName("TestUnloadedClass"),
+ "-Xmx50m",
+ "Test");
+ OutputAnalyzer output = new OutputAnalyzer(pb.start());
+ if (!Platform.isDebugBuild()) {
+ output.shouldContain("OutOfMemoryError");
+ }
+ }
+}
+
+class Test {
+ public static void main(String[] args) throws Exception {
+ long last = System.nanoTime();
+ for (int i = 0;;i++) {
+ if (Platform.isDebugBuild() && i >= 1000) {
+ // Debug build costs too much time to OOM so limit the loop iteration
+ break;
+ }
+ CustomClassLoader loader = new CustomClassLoader();
+ Class> k = loader.findClass("MyClass");
+ Constructor> c = k.getDeclaredConstructor();
+ c.setAccessible(true);
+ c.newInstance();
+
+ // call gc every ~1 second.
+ if ((System.nanoTime() - last) >= 1e9) {
+ System.gc();
+ last = System.nanoTime();
+ }
+ }
+ }
+}
+
+class CustomClassLoader extends ClassLoader {
+ static byte[] BYTES;
+
+ static {
+ try (InputStream in = CustomClassLoader.class.getResourceAsStream("MyClass.class")) {
+ try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
+ byte[] buf = new byte[4096];
+ int len;
+ while ((len = in.read(buf)) != -1) {
+ baos.write(buf, 0, len);
+ }
+ BYTES = baos.toByteArray();
+ }
+ } catch (Throwable t) {
+ throw new RuntimeException(t);
+ }
+ }
+
+ @Override
+ public Class findClass(String name) throws ClassNotFoundException {
+ return defineClass(name, BYTES, 0, BYTES.length);
+ }
+}
+
+class MyClass {
+}
diff --git a/test/hotspot/jtreg/serviceability/jvmti/GetMethodDeclaringClass/libTestUnloadedClass.cpp b/test/hotspot/jtreg/serviceability/jvmti/GetMethodDeclaringClass/libTestUnloadedClass.cpp
new file mode 100644
index 0000000000000..c32b787d57894
--- /dev/null
+++ b/test/hotspot/jtreg/serviceability/jvmti/GetMethodDeclaringClass/libTestUnloadedClass.cpp
@@ -0,0 +1,129 @@
+/*
+ * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
+ * Copyright (c) 2024, Alibaba Group Holding Limited. 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
+#include
+#include
+#include
+#include
+
+static jvmtiEnv *_jvmti;
+static JavaVM *_jvm;
+
+#define BUFFER_SIZE 100000
+static std::atomic ring_buffer[BUFFER_SIZE];
+
+void get_method_details(jmethodID method) {
+ jclass method_class;
+ char *class_name = NULL;
+ if (_jvmti->GetMethodDeclaringClass(method, &method_class) == JVMTI_ERROR_NONE) {
+ if (_jvmti->GetClassSignature(method_class, &class_name, NULL) == JVMTI_ERROR_NONE) {
+ _jvmti->Deallocate((unsigned char *)class_name);
+ }
+ }
+}
+
+void* read_ringbuffer(void* arg) {
+ JNIEnv *env;
+ _jvm->AttachCurrentThreadAsDaemon((void **)&env, NULL);
+ for (;;) {
+ jmethodID id = ring_buffer[rand() % BUFFER_SIZE].load(std::memory_order_relaxed);
+ if (id != (jmethodID)0) {
+ get_method_details(id);
+ }
+ }
+ return NULL;
+}
+
+static void JNICALL ClassPrepareCallback(jvmtiEnv *jvmti_env,
+ JNIEnv *jni_env,
+ jthread thread,
+ jclass klass) {
+ static bool reader_created = false;
+ static int ring_buffer_idx = 0;
+
+ char *class_name = NULL;
+ if (jvmti_env->GetClassSignature(klass, &class_name, NULL) != JVMTI_ERROR_NONE) {
+ return;
+ }
+ // We only care MyClass and only one thread loads it
+ bool is_my_class = strcmp(class_name, "LMyClass;") == 0;
+ jvmti_env->Deallocate((unsigned char *)class_name);
+ if (!is_my_class) {
+ return;
+ }
+
+ if (!reader_created) {
+ pthread_t tid;
+ pthread_create(&tid, NULL, read_ringbuffer, NULL);
+ reader_created = true;
+ }
+
+ jint method_count;
+ jmethodID *methods;
+ if (jvmti_env->GetClassMethods(klass, &method_count, &methods) == JVMTI_ERROR_NONE) {
+ ring_buffer[ring_buffer_idx++].store(methods[0], std::memory_order_relaxed);
+ ring_buffer_idx = ring_buffer_idx % BUFFER_SIZE;
+ jvmti_env->Deallocate((unsigned char *)methods);
+ }
+}
+
+JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) {
+ for (int i = 0; i < BUFFER_SIZE; i++) {
+ ring_buffer[i].store(0, std::memory_order_relaxed);
+ }
+
+ jvmtiEventCallbacks callbacks;
+ jvmtiError error;
+
+ _jvm = jvm;
+
+ if (jvm->GetEnv((void **)&_jvmti, JVMTI_VERSION_1_0) != JNI_OK) {
+ fprintf(stderr, "Unable to access JVMTI!\n");
+ return JNI_ERR;
+ }
+
+ // Set up the event callbacks
+ memset(&callbacks, 0, sizeof(callbacks));
+ callbacks.ClassPrepare = &ClassPrepareCallback;
+
+ // Register the callbacks
+ error = _jvmti->SetEventCallbacks(&callbacks, sizeof(callbacks));
+ if (error != JVMTI_ERROR_NONE) {
+ fprintf(stderr, "Error setting event callbacks: %d\n", error);
+ return JNI_ERR;
+ }
+
+ // Enable the ClassPrepare event
+ error = _jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_CLASS_PREPARE, NULL);
+ if (error != JVMTI_ERROR_NONE) {
+ fprintf(stderr, "Error enabling ClassPrepare event: %d\n", error);
+ return JNI_ERR;
+ }
+
+ return JNI_OK;
+}
diff --git a/test/jdk/java/awt/dnd/DropActionChangeTest.java b/test/jdk/java/awt/dnd/DropActionChangeTest.java
index 7cb1019a44de7..2bfbb44bbfd38 100644
--- a/test/jdk/java/awt/dnd/DropActionChangeTest.java
+++ b/test/jdk/java/awt/dnd/DropActionChangeTest.java
@@ -21,17 +21,17 @@
* questions.
*/
-import javax.swing.JFrame;
import java.awt.AWTEvent;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.Frame;
import java.awt.Panel;
import java.awt.Point;
+import java.awt.Rectangle;
import java.awt.Robot;
+import java.awt.Toolkit;
import java.awt.datatransfer.StringSelection;
import java.awt.dnd.DnDConstants;
-import java.awt.dnd.DragGestureEvent;
import java.awt.dnd.DragGestureListener;
import java.awt.dnd.DragSource;
import java.awt.dnd.DragSourceAdapter;
@@ -43,9 +43,13 @@
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetListener;
import java.awt.event.AWTEventListener;
-import java.awt.event.MouseEvent;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
+import java.awt.event.MouseEvent;
+import java.io.File;
+import java.util.concurrent.atomic.AtomicReference;
+import javax.imageio.ImageIO;
+import javax.swing.JFrame;
/*
@test
@@ -56,28 +60,24 @@
*/
public class DropActionChangeTest extends JFrame implements AWTEventListener {
- Robot robot;
- Frame frame;
+ private static Robot robot;
+ private static Frame frame;
+ private static volatile DropActionChangeTest test;
Panel panel;
private volatile boolean failed;
private volatile boolean dropEnd;
private volatile Component clickedComponent;
private final Object LOCK = new Object();
- static final int FRAME_ACTIVATION_TIMEOUT = 3000;
- static final int DROP_COMPLETION_TIMEOUT = 5000;
+ static final int DROP_COMPLETION_TIMEOUT = 8000;
static final int MOUSE_RELEASE_TIMEOUT = 2000;
public static void main(String[] args) throws Exception {
- DropActionChangeTest test = new DropActionChangeTest();
+ EventQueue.invokeAndWait(() -> test = new DropActionChangeTest());
EventQueue.invokeAndWait(test::init);
try {
test.start();
} finally {
- EventQueue.invokeAndWait(() -> {
- if (test.frame != null) {
- test.frame.dispose();
- }
- });
+ EventQueue.invokeAndWait(DropActionChangeTest::disposeFrame);
}
}
@@ -97,10 +97,12 @@ public void init() {
final DragSourceListener dsl = new DragSourceAdapter() {
public void dragDropEnd(DragSourceDropEvent e) {
- System.err.println("DragSourseListener.dragDropEnd(): " +
+ System.err.println("DragSourceListener.dragDropEnd(): " +
"drop action=" + e.getDropAction());
if (e.getDropAction() != DnDConstants.ACTION_MOVE) {
- System.err.println("FAILURE: wrong drop action:" + e.getDropAction());
+ System.err.println("FAILURE: wrong drop action:"
+ + e.getDropAction() + ", It should be "
+ + DnDConstants.ACTION_MOVE);
failed = true;
}
synchronized (LOCK) {
@@ -110,11 +112,7 @@ public void dragDropEnd(DragSourceDropEvent e) {
}
};
- DragGestureListener dgl = new DragGestureListener() {
- public void dragGestureRecognized(DragGestureEvent dge) {
- dge.startDrag(null, new StringSelection("test"), dsl);
- }
- };
+ DragGestureListener dgl = dge -> dge.startDrag(null, new StringSelection("test"), dsl);
new DragSource().createDefaultDragGestureRecognizer(panel,
DnDConstants.ACTION_COPY_OR_MOVE, dgl);
@@ -142,11 +140,25 @@ public void drop(DropTargetDropEvent e) {
frame.setVisible(true);
}
+ private static void disposeFrame() {
+ if (frame != null) {
+ frame.dispose();
+ }
+ if (test != null) {
+ test.dispose();
+ }
+ }
+
public void start() {
try {
robot = new Robot();
+ robot.setAutoDelay(100);
+ robot.waitForIdle();
+ robot.delay(500);
- Point startPoint = panel.getLocationOnScreen();
+ AtomicReference startPointRef = new AtomicReference<>();
+ EventQueue.invokeAndWait(()-> startPointRef.set(panel.getLocationOnScreen()));
+ Point startPoint = startPointRef.get();
startPoint.translate(50, 50);
if (!pointInComponent(robot, startPoint, panel)) {
@@ -163,15 +175,18 @@ public void start() {
synchronized (LOCK) {
robot.keyPress(KeyEvent.VK_CONTROL);
robot.mouseMove(startPoint.x, startPoint.y);
- robot.mousePress(InputEvent.BUTTON1_MASK);
+ robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
Util.doDrag(robot, startPoint, medPoint);
+ robot.delay(500);
robot.keyRelease(KeyEvent.VK_CONTROL);
Util.doDrag(robot, medPoint, endPoint);
- robot.mouseRelease(InputEvent.BUTTON1_MASK);
+ robot.delay(500);
+ robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
LOCK.wait(DROP_COMPLETION_TIMEOUT);
}
if (!dropEnd) {
- System.err.println("DragSourseListener.dragDropEnd() was not called, returning");
+ captureScreen("No_Drop_End_");
+ System.err.println("DragSourceListener.dragDropEnd() was not called, returning");
return;
}
} catch (Throwable e) {
@@ -179,10 +194,22 @@ public void start() {
}
if (failed) {
- throw new RuntimeException("wrong drop action!");
+ captureScreen("Wrong_Drop_Action_");
+ throw new RuntimeException("Wrong drop action!");
}
- System.err.println("test passed!");
+ System.err.println("Test passed!");
+ }
+
+ private static void captureScreen(String str) {
+ try {
+ final Rectangle screenBounds = new Rectangle(
+ Toolkit.getDefaultToolkit().getScreenSize());
+ ImageIO.write(robot.createScreenCapture(screenBounds), "png",
+ new File(str + "Failure_Screen.png"));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
}
public void reset() {
@@ -203,9 +230,9 @@ boolean pointInComponent(Robot robot, Point p, Component comp)
robot.waitForIdle();
reset();
robot.mouseMove(p.x, p.y);
- robot.mousePress(InputEvent.BUTTON1_MASK);
+ robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
synchronized (LOCK) {
- robot.mouseRelease(InputEvent.BUTTON1_MASK);
+ robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
LOCK.wait(MOUSE_RELEASE_TIMEOUT);
}
@@ -227,15 +254,11 @@ public static int sign(int n) {
}
public static void doDrag(Robot robot, Point startPoint, Point endPoint) {
+ robot.waitForIdle();
for (Point p = new Point(startPoint); !p.equals(endPoint);
p.translate(Util.sign(endPoint.x - p.x),
Util.sign(endPoint.y - p.y))) {
robot.mouseMove(p.x, p.y);
- try {
- Thread.sleep(100);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
}
}
-}
+}
\ No newline at end of file
diff --git a/test/jdk/sun/security/pkcs11/Provider/RequiredMechCheck.cfg b/test/jdk/sun/security/pkcs11/Provider/RequiredMechCheck.cfg
new file mode 100644
index 0000000000000..906e4a3a3625e
--- /dev/null
+++ b/test/jdk/sun/security/pkcs11/Provider/RequiredMechCheck.cfg
@@ -0,0 +1,14 @@
+name = NSS
+
+showInfo = true
+
+slot = 1
+
+library = ${pkcs11test.nss.lib}
+
+disabledMechanisms = {
+ CKM_SHA224_HMAC
+ CKM_SHA256_HMAC
+}
+
+nssArgs = "configdir='${pkcs11test.nss.db}' certPrefix='' keyPrefix=''"
diff --git a/test/jdk/sun/security/pkcs11/Provider/RequiredMechCheck.java b/test/jdk/sun/security/pkcs11/Provider/RequiredMechCheck.java
new file mode 100644
index 0000000000000..11fb562a82548
--- /dev/null
+++ b/test/jdk/sun/security/pkcs11/Provider/RequiredMechCheck.java
@@ -0,0 +1,116 @@
+/*
+ * 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 8335288
+ * @library /test/lib ..
+ * @modules jdk.crypto.cryptoki
+ * @summary check that if any required mech is unavailable, then the
+ * mechanism will be unavailable as well.
+ * @run testng/othervm RequiredMechCheck
+ */
+import java.nio.file.Path;
+import java.security.Provider;
+import java.security.NoSuchAlgorithmException;
+import javax.crypto.Cipher;
+import javax.crypto.Mac;
+import javax.crypto.SecretKeyFactory;
+
+import jtreg.SkippedException;
+import org.testng.SkipException;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+public class RequiredMechCheck extends PKCS11Test {
+
+ private static record TestData(String serviceType, String algo,
+ boolean disabled) {}
+
+ private static TestData[] testValues = {
+ new TestData("MAC", "HmacPBESHA1", false),
+ new TestData("MAC", "HmacPBESHA224", true),
+ new TestData("MAC", "HmacPBESHA256", true),
+ new TestData("MAC", "HmacPBESHA384", false),
+ new TestData("MAC", "HmacPBESHA512", false),
+ new TestData("SKF", "PBEWithHmacSHA1AndAES_128", false),
+ new TestData("SKF", "PBEWithHmacSHA224AndAES_128", true),
+ new TestData("SKF", "PBEWithHmacSHA256AndAES_128", true),
+ new TestData("SKF", "PBEWithHmacSHA384AndAES_128", false),
+ new TestData("SKF", "PBEWithHmacSHA512AndAES_128", false),
+ new TestData("CIP", "PBEWithHmacSHA1AndAES_128", false),
+ new TestData("CIP", "PBEWithHmacSHA224AndAES_128", true),
+ new TestData("CIP", "PBEWithHmacSHA256AndAES_128", true),
+ new TestData("CIP", "PBEWithHmacSHA384AndAES_128", false),
+ new TestData("CIP", "PBEWithHmacSHA512AndAES_128", false),
+ };
+
+ @BeforeClass
+ public void setUp() throws Exception {
+ Path configPath = Path.of(BASE).resolve("RequiredMechCheck.cfg");
+ System.setProperty("CUSTOM_P11_CONFIG", configPath.toString());
+ }
+
+ @Test
+ public void test() throws Exception {
+ try {
+ main(new RequiredMechCheck());
+ } catch (SkippedException se) {
+ throw new SkipException("One or more tests are skipped");
+ }
+ }
+
+ public void main(Provider p) throws Exception {
+ for (TestData td : testValues) {
+ String desc = td.serviceType + " " + td.algo;
+ Object t;
+ try {
+ switch (td.serviceType) {
+ case "MAC":
+ t = Mac.getInstance(td.algo, p);
+ break;
+ case "SKF":
+ t = SecretKeyFactory.getInstance(td.algo, p);
+ break;
+ case "CIP":
+ t = Cipher.getInstance(td.algo, p);
+ break;
+ default:
+ throw new RuntimeException("Unsupported Test Type!");
+ }
+
+ if (td.disabled) {
+ throw new RuntimeException("Fail, no NSAE for " + desc);
+ } else {
+ System.out.println("Ok, getInstance() works for " + desc);
+ }
+ } catch (NoSuchAlgorithmException e) {
+ if (td.disabled) {
+ System.out.println("Ok, NSAE thrown for " + desc);
+ } else {
+ throw new RuntimeException("Unexpected Ex for " + desc, e);
+ }
+ }
+ }
+ }
+}