Merge branch 'openjdk:master' into cas-alloc-1

This commit is contained in:
Xiaolong Peng 2026-01-08 15:50:08 -08:00 committed by GitHub
commit 0b04841f33
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
95 changed files with 1542 additions and 1197 deletions

View File

@ -97,7 +97,7 @@ jobs:
--with-zlib=system
--with-jmod-compress=zip-1
--with-external-symbols-in-bundles=none
--with-debug-info-level=1
--with-native-debug-symbols-level=1
${{ inputs.extra-conf-options }} ${{ inputs.configure-arguments }} || (
echo "Dumping config.log:" &&
cat config.log &&

View File

@ -180,7 +180,7 @@ jobs:
--with-sysroot=sysroot
--with-jmod-compress=zip-1
--with-external-symbols-in-bundles=none
--with-debug-info-level=1
--with-native-debug-symbols-level=1
CC=${{ matrix.gnu-arch }}-linux-gnu${{ matrix.gnu-abi}}-gcc-${{ inputs.gcc-major-version }}
CXX=${{ matrix.gnu-arch }}-linux-gnu${{ matrix.gnu-abi}}-g++-${{ inputs.gcc-major-version }}
${{ inputs.extra-conf-options }} ${{ inputs.configure-arguments }} || (

View File

@ -144,7 +144,7 @@ jobs:
--with-zlib=system
--with-jmod-compress=zip-1
--with-external-symbols-in-bundles=none
--with-debug-info-level=1
--with-native-debug-symbols-level=1
${{ inputs.extra-conf-options }} ${{ inputs.configure-arguments }} || (
echo "Dumping config.log:" &&
cat config.log &&

View File

@ -111,7 +111,7 @@ jobs:
--with-zlib=system
--with-jmod-compress=zip-1
--with-external-symbols-in-bundles=none
--with-debug-info-level=1
--with-native-debug-symbols-level=1
${{ inputs.extra-conf-options }} ${{ inputs.configure-arguments }} || (
echo "Dumping config.log:" &&
cat config.log &&

View File

@ -69,20 +69,20 @@ AC_DEFUN([FLAGS_SETUP_DEBUG_SYMBOLS],
# Debug prefix mapping if supported by compiler
DEBUG_PREFIX_CFLAGS=
UTIL_ARG_WITH(NAME: debug-info-level, TYPE: string,
UTIL_ARG_WITH(NAME: native-debug-symbols-level, TYPE: string,
DEFAULT: "",
RESULT: DEBUG_INFO_LEVEL,
DESC: [Sets the debug info level, when debug info generation is enabled (GCC and Clang only)],
DEFAULT_DESC: [default])
AC_SUBST(DEBUG_INFO_LEVEL)
RESULT: DEBUG_SYMBOLS_LEVEL,
DESC: [set the native debug symbol level (GCC and Clang only)],
DEFAULT_DESC: [toolchain default])
AC_SUBST(DEBUG_SYMBOLS_LEVEL)
if test "x${TOOLCHAIN_TYPE}" = xgcc || \
test "x${TOOLCHAIN_TYPE}" = xclang; then
DEBUG_INFO_LEVEL_FLAGS="-g"
if test "x${DEBUG_INFO_LEVEL}" != "x"; then
DEBUG_INFO_LEVEL_FLAGS="-g${DEBUG_INFO_LEVEL}"
FLAGS_COMPILER_CHECK_ARGUMENTS(ARGUMENT: [${DEBUG_INFO_LEVEL_FLAGS}],
IF_FALSE: AC_MSG_ERROR("Debug info level ${DEBUG_INFO_LEVEL} is not supported"))
DEBUG_SYMBOLS_LEVEL_FLAGS="-g"
if test "x${DEBUG_SYMBOLS_LEVEL}" != "x"; then
DEBUG_SYMBOLS_LEVEL_FLAGS="-g${DEBUG_SYMBOLS_LEVEL}"
FLAGS_COMPILER_CHECK_ARGUMENTS(ARGUMENT: [${DEBUG_SYMBOLS_LEVEL_FLAGS}],
IF_FALSE: AC_MSG_ERROR("Debug info level ${DEBUG_SYMBOLS_LEVEL} is not supported"))
fi
fi
@ -111,8 +111,8 @@ AC_DEFUN([FLAGS_SETUP_DEBUG_SYMBOLS],
fi
# Debug info level should follow the debug format to be effective.
CFLAGS_DEBUG_SYMBOLS="-gdwarf-4 ${DEBUG_INFO_LEVEL_FLAGS}"
ASFLAGS_DEBUG_SYMBOLS="${DEBUG_INFO_LEVEL_FLAGS}"
CFLAGS_DEBUG_SYMBOLS="-gdwarf-4 ${DEBUG_SYMBOLS_LEVEL_FLAGS}"
ASFLAGS_DEBUG_SYMBOLS="${DEBUG_SYMBOLS_LEVEL_FLAGS}"
elif test "x$TOOLCHAIN_TYPE" = xclang; then
if test "x$ALLOW_ABSOLUTE_PATHS_IN_OUTPUT" = "xfalse"; then
# Check if compiler supports -fdebug-prefix-map. If so, use that to make
@ -132,8 +132,8 @@ AC_DEFUN([FLAGS_SETUP_DEBUG_SYMBOLS],
IF_FALSE: [GDWARF_FLAGS=""])
# Debug info level should follow the debug format to be effective.
CFLAGS_DEBUG_SYMBOLS="${GDWARF_FLAGS} ${DEBUG_INFO_LEVEL_FLAGS}"
ASFLAGS_DEBUG_SYMBOLS="${DEBUG_INFO_LEVEL_FLAGS}"
CFLAGS_DEBUG_SYMBOLS="${GDWARF_FLAGS} ${DEBUG_SYMBOLS_LEVEL_FLAGS}"
ASFLAGS_DEBUG_SYMBOLS="${DEBUG_SYMBOLS_LEVEL_FLAGS}"
elif test "x$TOOLCHAIN_TYPE" = xmicrosoft; then
CFLAGS_DEBUG_SYMBOLS="-Z7"
fi

View File

@ -286,7 +286,7 @@ public class ClassGenerator {
diagnosticFlags.isEmpty() ?
StubKind.DIAGNOSTIC_FLAGS_EMPTY.format() :
StubKind.DIAGNOSTIC_FLAGS_NON_EMPTY.format(diagnosticFlags),
StubKind.LINT_CATEGORY.format("\"" + lintCategory + "\""),
StubKind.LINT_CATEGORY.format(toLintFieldName(lintCategory)),
"\"" + keyParts[0] + "\"",
"\"" + Stream.of(keyParts).skip(2).collect(Collectors.joining(".")) + "\"",
javadoc);
@ -314,7 +314,7 @@ public class ClassGenerator {
diagnosticFlags.isEmpty() ?
StubKind.DIAGNOSTIC_FLAGS_EMPTY.format() :
StubKind.DIAGNOSTIC_FLAGS_NON_EMPTY.format(diagnosticFlags),
StubKind.LINT_CATEGORY.format("\"" + lintCategory + "\""),
StubKind.LINT_CATEGORY.format(toLintFieldName(lintCategory)),
"\"" + keyParts[0] + "\"",
"\"" + Stream.of(keyParts).skip(2).collect(Collectors.joining(".")) + "\"",
argNames.stream().collect(Collectors.joining(", ")));
@ -329,6 +329,11 @@ public class ClassGenerator {
}
}
String toLintFieldName(String lintCategory) {
return lintCategory.toUpperCase()
.replaceAll("-", "_");
}
/**
* Form the name of a factory method/field given a resource key.
*/

View File

@ -87,7 +87,7 @@ suppress.warnings=\
@SuppressWarnings("rawtypes")\n
lint.category=\
LintCategory.get({0}).get()
LintCategory.{0}
diagnostic.flags.empty=\
EnumSet.noneOf(DiagnosticFlag.class)

View File

@ -30,7 +30,7 @@
#include "code/nativeInst.hpp"
#include "code/vtableStubs.hpp"
#include "compiler/disassembler.hpp"
#include "cppstdlib/cstdlib.h"
#include "cppstdlib/cstdlib.hpp"
#include "interpreter/interpreter.hpp"
#include "jvm.h"
#include "memory/allocation.inline.hpp"

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -116,6 +116,10 @@ bool AOTConstantPoolResolver::is_class_resolution_deterministic(InstanceKlass* c
return false;
}
} else if (resolved_class->is_objArray_klass()) {
if (CDSConfig::is_dumping_dynamic_archive()) {
// This is difficult to handle. See JDK-8374639
return false;
}
Klass* elem = ObjArrayKlass::cast(resolved_class)->bottom_klass();
if (elem->is_instance_klass()) {
return is_class_resolution_deterministic(cp_holder, InstanceKlass::cast(elem));

View File

@ -696,7 +696,7 @@ template <typename T> void AOTMappedHeapWriter::relocate_field_in_buffer(T* fiel
// We use zero-based, 0-shift encoding, so the narrowOop is just the lower
// 32 bits of request_referent
intptr_t addr = cast_from_oop<intptr_t>(request_referent);
*((narrowOop*)field_addr_in_buffer) = checked_cast<narrowOop>(addr);
*((narrowOop*)field_addr_in_buffer) = CompressedOops::narrow_oop_cast(addr);
} else {
store_requested_oop_in_buffer<T>(field_addr_in_buffer, request_referent);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -2159,7 +2159,6 @@ void AOTMetaspace::initialize_shared_spaces() {
intptr_t* buffer = (intptr_t*)dynamic_mapinfo->serialized_data();
ReadClosure rc(&buffer, (intptr_t)SharedBaseAddress);
DynamicArchive::serialize(&rc);
DynamicArchive::setup_array_klasses();
}
LogStreamHandle(Info, aot) lsh;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -984,8 +984,6 @@ void ArchiveBuilder::make_klasses_shareable() {
#undef STATS_FORMAT
#undef STATS_PARAMS
DynamicArchive::make_array_klasses_shareable();
}
void ArchiveBuilder::make_training_data_shareable() {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -48,6 +48,7 @@
#include "logging/log.hpp"
#include "memory/metaspaceClosure.hpp"
#include "memory/resourceArea.hpp"
#include "oops/array.hpp"
#include "oops/klass.inline.hpp"
#include "runtime/arguments.hpp"
#include "runtime/os.hpp"
@ -95,7 +96,6 @@ public:
void sort_methods(InstanceKlass* ik) const;
void remark_pointers_for_instance_klass(InstanceKlass* k, bool should_mark) const;
void write_archive(char* serialized_data, AOTClassLocationConfig* cl_config);
void gather_array_klasses();
public:
// Do this before and after the archive dump to see if any corruption
@ -132,7 +132,6 @@ public:
init_header();
gather_source_objs();
gather_array_klasses();
reserve_buffer();
log_info(cds, dynamic)("Copying %d klasses and %d symbols",
@ -159,7 +158,6 @@ public:
ArchiveBuilder::OtherROAllocMark mark;
SystemDictionaryShared::write_to_archive(false);
cl_config = AOTClassLocationConfig::dumptime()->write_to_archive();
DynamicArchive::dump_array_klasses();
serialized_data = ro_region()->top();
WriteClosure wc(ro_region());
@ -175,8 +173,6 @@ public:
write_archive(serialized_data, cl_config);
release_header();
DynamicArchive::post_dump();
post_dump();
verify_universe("After CDS dynamic dump");
@ -185,30 +181,6 @@ public:
virtual void iterate_roots(MetaspaceClosure* it) {
AOTArtifactFinder::all_cached_classes_do(it);
SystemDictionaryShared::dumptime_classes_do(it);
iterate_primitive_array_klasses(it);
}
void iterate_primitive_array_klasses(MetaspaceClosure* it) {
for (int i = T_BOOLEAN; i <= T_LONG; i++) {
assert(is_java_primitive((BasicType)i), "sanity");
Klass* k = Universe::typeArrayKlass((BasicType)i); // this give you "[I", etc
assert(AOTMetaspace::in_aot_cache_static_region((void*)k),
"one-dimensional primitive array should be in static archive");
ArrayKlass* ak = ArrayKlass::cast(k);
while (ak != nullptr && ak->in_aot_cache()) {
Klass* next_k = ak->array_klass_or_null();
if (next_k != nullptr) {
ak = ArrayKlass::cast(next_k);
} else {
ak = nullptr;
}
}
if (ak != nullptr) {
assert(ak->dimension() > 1, "sanity");
// this is the lowest dimension that's not in the static archive
it->push(&ak);
}
}
}
};
@ -367,26 +339,6 @@ void DynamicArchiveBuilder::write_archive(char* serialized_data, AOTClassLocatio
log_info(cds, dynamic)("%d klasses; %d symbols", klasses()->length(), symbols()->length());
}
void DynamicArchiveBuilder::gather_array_klasses() {
for (int i = 0; i < klasses()->length(); i++) {
if (klasses()->at(i)->is_objArray_klass()) {
ObjArrayKlass* oak = ObjArrayKlass::cast(klasses()->at(i));
Klass* elem = oak->element_klass();
if (AOTMetaspace::in_aot_cache_static_region(elem)) {
// Only capture the array klass whose element_klass is in the static archive.
// During run time, setup (see DynamicArchive::setup_array_klasses()) is needed
// so that the element_klass can find its array klasses from the dynamic archive.
DynamicArchive::append_array_klass(oak);
} else {
// The element_klass and its array klasses are in the same archive.
assert(!AOTMetaspace::in_aot_cache_static_region(oak),
"we should not gather klasses that are already in the static archive");
}
}
}
log_debug(aot)("Total array klasses gathered for dynamic archive: %d", DynamicArchive::num_array_klasses());
}
class VM_PopulateDynamicDumpSharedSpace: public VM_Heap_Sync_Operation {
DynamicArchiveBuilder _builder;
public:
@ -403,76 +355,9 @@ public:
}
};
// _array_klasses and _dynamic_archive_array_klasses only hold the array klasses
// which have element klass in the static archive.
GrowableArray<ObjArrayKlass*>* DynamicArchive::_array_klasses = nullptr;
Array<ObjArrayKlass*>* DynamicArchive::_dynamic_archive_array_klasses = nullptr;
void DynamicArchive::serialize(SerializeClosure* soc) {
SymbolTable::serialize_shared_table_header(soc, false);
SystemDictionaryShared::serialize_dictionary_headers(soc, false);
soc->do_ptr(&_dynamic_archive_array_klasses);
}
void DynamicArchive::append_array_klass(ObjArrayKlass* ak) {
if (_array_klasses == nullptr) {
_array_klasses = new (mtClassShared) GrowableArray<ObjArrayKlass*>(50, mtClassShared);
}
_array_klasses->append(ak);
}
void DynamicArchive::dump_array_klasses() {
assert(CDSConfig::is_dumping_dynamic_archive(), "sanity");
if (_array_klasses != nullptr) {
ArchiveBuilder* builder = ArchiveBuilder::current();
int num_array_klasses = _array_klasses->length();
_dynamic_archive_array_klasses =
ArchiveBuilder::new_ro_array<ObjArrayKlass*>(num_array_klasses);
for (int i = 0; i < num_array_klasses; i++) {
builder->write_pointer_in_buffer(_dynamic_archive_array_klasses->adr_at(i), _array_klasses->at(i));
}
}
}
void DynamicArchive::setup_array_klasses() {
if (_dynamic_archive_array_klasses != nullptr) {
for (int i = 0; i < _dynamic_archive_array_klasses->length(); i++) {
ObjArrayKlass* oak = _dynamic_archive_array_klasses->at(i);
Klass* elm = oak->element_klass();
assert(AOTMetaspace::in_aot_cache_static_region((void*)elm), "must be");
if (elm->is_instance_klass()) {
assert(InstanceKlass::cast(elm)->array_klasses() == nullptr, "must be");
InstanceKlass::cast(elm)->set_array_klasses(oak);
} else {
assert(elm->is_array_klass(), "sanity");
assert(ArrayKlass::cast(elm)->higher_dimension() == nullptr, "must be");
ArrayKlass::cast(elm)->set_higher_dimension(oak);
}
}
log_debug(aot)("Total array klasses read from dynamic archive: %d", _dynamic_archive_array_klasses->length());
}
}
void DynamicArchive::make_array_klasses_shareable() {
if (_array_klasses != nullptr) {
int num_array_klasses = _array_klasses->length();
for (int i = 0; i < num_array_klasses; i++) {
ObjArrayKlass* k = ArchiveBuilder::current()->get_buffered_addr(_array_klasses->at(i));
k->remove_unshareable_info();
}
}
}
void DynamicArchive::post_dump() {
if (_array_klasses != nullptr) {
delete _array_klasses;
_array_klasses = nullptr;
}
}
int DynamicArchive::num_array_klasses() {
return _array_klasses != nullptr ? _array_klasses->length() : 0;
}
void DynamicArchive::dump_impl(bool jcmd_request, const char* archive_name, TRAPS) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -26,13 +26,8 @@
#define SHARE_CDS_DYNAMICARCHIVE_HPP
#include "cds/filemap.hpp"
#include "classfile/compactHashtable.hpp"
#include "memory/allStatic.hpp"
#include "memory/memRegion.hpp"
#include "oops/array.hpp"
#include "oops/oop.hpp"
#include "utilities/exceptions.hpp"
#include "utilities/growableArray.hpp"
#include "utilities/macros.hpp"
#if INCLUDE_CDS
@ -59,22 +54,13 @@ public:
};
class DynamicArchive : AllStatic {
private:
static GrowableArray<ObjArrayKlass*>* _array_klasses;
static Array<ObjArrayKlass*>* _dynamic_archive_array_klasses;
public:
static void dump_for_jcmd(const char* archive_name, TRAPS);
static void dump_at_exit(JavaThread* current);
static void dump_impl(bool jcmd_request, const char* archive_name, TRAPS);
static bool is_mapped() { return FileMapInfo::dynamic_info() != nullptr; }
static bool validate(FileMapInfo* dynamic_info);
static void dump_array_klasses();
static void setup_array_klasses();
static void append_array_klass(ObjArrayKlass* oak);
static void serialize(SerializeClosure* soc);
static void make_array_klasses_shareable();
static void post_dump();
static int num_array_klasses();
};
#endif // INCLUDE_CDS
#endif // SHARE_CDS_DYNAMICARCHIVE_HPP

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -4297,10 +4297,6 @@ int jdk_internal_foreign_abi_NativeEntryPoint::_downcall_stub_address_offset;
macro(_method_type_offset, k, "methodType", java_lang_invoke_MethodType_signature, false); \
macro(_downcall_stub_address_offset, k, "downcallStubAddress", long_signature, false);
bool jdk_internal_foreign_abi_NativeEntryPoint::is_instance(oop obj) {
return obj != nullptr && is_subclass(obj->klass());
}
void jdk_internal_foreign_abi_NativeEntryPoint::compute_offsets() {
InstanceKlass* k = vmClasses::NativeEntryPoint_klass();
NEP_FIELDS_DO(FIELD_COMPUTE_OFFSET);
@ -4337,10 +4333,6 @@ int jdk_internal_foreign_abi_ABIDescriptor::_scratch2_offset;
macro(_scratch1_offset, k, "scratch1", jdk_internal_foreign_abi_VMStorage_signature, false); \
macro(_scratch2_offset, k, "scratch2", jdk_internal_foreign_abi_VMStorage_signature, false);
bool jdk_internal_foreign_abi_ABIDescriptor::is_instance(oop obj) {
return obj != nullptr && is_subclass(obj->klass());
}
void jdk_internal_foreign_abi_ABIDescriptor::compute_offsets() {
InstanceKlass* k = vmClasses::ABIDescriptor_klass();
ABIDescriptor_FIELDS_DO(FIELD_COMPUTE_OFFSET);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -1179,13 +1179,6 @@ class jdk_internal_foreign_abi_NativeEntryPoint: AllStatic {
static oop method_type(oop entry);
static jlong downcall_stub_address(oop entry);
// Testers
static bool is_subclass(Klass* klass) {
return vmClasses::NativeEntryPoint_klass() != nullptr &&
klass->is_subclass_of(vmClasses::NativeEntryPoint_klass());
}
static bool is_instance(oop obj);
// Accessors for code generation:
static int method_type_offset_in_bytes() { return _method_type_offset; }
static int downcall_stub_address_offset_in_bytes() { return _downcall_stub_address_offset; }
@ -1216,13 +1209,6 @@ class jdk_internal_foreign_abi_ABIDescriptor: AllStatic {
static jint shadowSpace(oop entry);
static oop scratch1(oop entry);
static oop scratch2(oop entry);
// Testers
static bool is_subclass(Klass* klass) {
return vmClasses::ABIDescriptor_klass() != nullptr &&
klass->is_subclass_of(vmClasses::ABIDescriptor_klass());
}
static bool is_instance(oop obj);
};
class jdk_internal_foreign_abi_VMStorage: AllStatic {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -33,6 +33,7 @@
#include "memory/universe.hpp"
#include "oops/access.inline.hpp"
#include "oops/method.inline.hpp"
#include "runtime/atomic.hpp"
#include "runtime/frame.inline.hpp"
#include "runtime/javaThread.hpp"
#include "runtime/threads.hpp"
@ -196,8 +197,8 @@ int BarrierSetNMethod::nmethod_stub_entry_barrier(address* return_address_ptr) {
// Diagnostic option to force deoptimization 1 in 10 times. It is otherwise
// a very rare event.
if (DeoptimizeNMethodBarriersALot && !nm->is_osr_method()) {
static volatile uint32_t counter=0;
if (AtomicAccess::add(&counter, 1u) % 10 == 0) {
static Atomic<uint32_t> counter{0};
if (counter.add_then_fetch(1u) % 10 == 0) {
may_enter = false;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -23,7 +23,7 @@
*/
#include "gc/shared/concurrentGCThread.hpp"
#include "runtime/atomicAccess.hpp"
#include "runtime/atomic.hpp"
#include "runtime/init.hpp"
#include "runtime/jniHandles.hpp"
#include "runtime/mutexLocker.hpp"
@ -48,7 +48,7 @@ void ConcurrentGCThread::run() {
// Signal thread has terminated
MonitorLocker ml(Terminator_lock);
AtomicAccess::release_store(&_has_terminated, true);
_has_terminated.release_store(true);
ml.notify_all();
}
@ -57,21 +57,21 @@ void ConcurrentGCThread::stop() {
assert(!has_terminated(), "Invalid state");
// Signal thread to terminate
AtomicAccess::release_store_fence(&_should_terminate, true);
_should_terminate.release_store_fence(true);
stop_service();
// Wait for thread to terminate
MonitorLocker ml(Terminator_lock);
while (!_has_terminated) {
while (!_has_terminated.load_relaxed()) {
ml.wait();
}
}
bool ConcurrentGCThread::should_terminate() const {
return AtomicAccess::load_acquire(&_should_terminate);
return _should_terminate.load_acquire();
}
bool ConcurrentGCThread::has_terminated() const {
return AtomicAccess::load_acquire(&_has_terminated);
return _has_terminated.load_acquire();
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -25,14 +25,15 @@
#ifndef SHARE_GC_SHARED_CONCURRENTGCTHREAD_HPP
#define SHARE_GC_SHARED_CONCURRENTGCTHREAD_HPP
#include "runtime/atomic.hpp"
#include "runtime/javaThread.hpp"
#include "runtime/nonJavaThread.hpp"
#include "utilities/debug.hpp"
class ConcurrentGCThread: public NamedThread {
private:
volatile bool _should_terminate;
volatile bool _has_terminated;
Atomic<bool> _should_terminate;
Atomic<bool> _has_terminated;
protected:
void create_and_start(ThreadPriority prio = NearMaxPriority);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -28,7 +28,7 @@
#include "logging/log.hpp"
#include "memory/resourceArea.hpp"
#include "memory/universe.hpp"
#include "runtime/atomicAccess.hpp"
#include "runtime/atomic.hpp"
#include "runtime/interfaceSupport.inline.hpp"
#include "runtime/javaThread.inline.hpp"
#include "runtime/safepoint.hpp"
@ -60,16 +60,13 @@ public:
};
Monitor* GCLocker::_lock;
volatile bool GCLocker::_is_gc_request_pending;
Atomic<bool> GCLocker::_is_gc_request_pending{false};
DEBUG_ONLY(uint64_t GCLocker::_verify_in_cr_count;)
DEBUG_ONLY(Atomic<uint64_t> GCLocker::_verify_in_cr_count{0};)
void GCLocker::initialize() {
assert(JNICritical_lock != nullptr, "inv");
_lock = JNICritical_lock;
_is_gc_request_pending = false;
DEBUG_ONLY(_verify_in_cr_count = 0;)
}
bool GCLocker::is_active() {
@ -84,11 +81,11 @@ bool GCLocker::is_active() {
void GCLocker::block() {
// _lock is held from the beginning of block() to the end of of unblock().
_lock->lock();
assert(AtomicAccess::load(&_is_gc_request_pending) == false, "precondition");
assert(_is_gc_request_pending.load_relaxed() == false, "precondition");
GCLockerTimingDebugLogger logger("Thread blocked to start GC.");
AtomicAccess::store(&_is_gc_request_pending, true);
_is_gc_request_pending.store_relaxed(true);
// The _is_gc_request_pending and _jni_active_critical (inside
// in_critical_atomic()) variables form a Dekker duality. On the GC side, the
@ -112,14 +109,14 @@ void GCLocker::block() {
#ifdef ASSERT
// Matching the storestore in GCLocker::exit.
OrderAccess::loadload();
assert(AtomicAccess::load(&_verify_in_cr_count) == 0, "inv");
assert(_verify_in_cr_count.load_relaxed() == 0, "inv");
#endif
}
void GCLocker::unblock() {
assert(AtomicAccess::load(&_is_gc_request_pending) == true, "precondition");
assert(_is_gc_request_pending.load_relaxed() == true, "precondition");
AtomicAccess::store(&_is_gc_request_pending, false);
_is_gc_request_pending.store_relaxed(false);
_lock->unlock();
}
@ -139,7 +136,7 @@ void GCLocker::enter_slow(JavaThread* current_thread) {
// Same as fast path.
OrderAccess::fence();
if (!AtomicAccess::load(&_is_gc_request_pending)) {
if (!_is_gc_request_pending.load_relaxed()) {
return;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -27,6 +27,7 @@
#include "gc/shared/gcCause.hpp"
#include "memory/allStatic.hpp"
#include "runtime/atomic.hpp"
#include "runtime/mutex.hpp"
// GCLocker provides synchronization between the garbage collector (GC) and
@ -43,11 +44,11 @@
class GCLocker: public AllStatic {
static Monitor* _lock;
static volatile bool _is_gc_request_pending;
static Atomic<bool> _is_gc_request_pending;
#ifdef ASSERT
// Debug-only: to track the number of java threads in critical-region.
static uint64_t _verify_in_cr_count;
static Atomic<uint64_t> _verify_in_cr_count;
#endif
static void enter_slow(JavaThread* current_thread);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -38,13 +38,13 @@ void GCLocker::enter(JavaThread* current_thread) {
// Matching the fence in GCLocker::block.
OrderAccess::fence();
if (AtomicAccess::load(&_is_gc_request_pending)) {
if (_is_gc_request_pending.load_relaxed()) {
current_thread->exit_critical();
// slow-path
enter_slow(current_thread);
}
DEBUG_ONLY(AtomicAccess::add(&_verify_in_cr_count, (uint64_t)1);)
DEBUG_ONLY(_verify_in_cr_count.add_then_fetch(1u);)
} else {
current_thread->enter_critical();
}
@ -55,7 +55,7 @@ void GCLocker::exit(JavaThread* current_thread) {
#ifdef ASSERT
if (current_thread->in_last_critical()) {
AtomicAccess::add(&_verify_in_cr_count, (uint64_t)-1);
_verify_in_cr_count.sub_then_fetch(1u);
// Matching the loadload in GCLocker::block.
OrderAccess::storestore();
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -25,7 +25,7 @@
#include "gc/shared/gc_globals.hpp"
#include "gc/shared/pretouchTask.hpp"
#include "logging/log.hpp"
#include "runtime/atomicAccess.hpp"
#include "runtime/atomic.hpp"
#include "runtime/globals.hpp"
#include "runtime/os.hpp"
#include "utilities/align.hpp"
@ -52,11 +52,11 @@ size_t PretouchTask::chunk_size() {
void PretouchTask::work(uint worker_id) {
while (true) {
char* cur_start = AtomicAccess::load(&_cur_addr);
char* cur_start = _cur_addr.load_relaxed();
char* cur_end = cur_start + MIN2(_chunk_size, pointer_delta(_end_addr, cur_start, 1));
if (cur_start >= cur_end) {
break;
} else if (cur_start == AtomicAccess::cmpxchg(&_cur_addr, cur_start, cur_end)) {
} else if (cur_start == _cur_addr.compare_exchange(cur_start, cur_end)) {
os::pretouch_memory(cur_start, cur_end, _page_size);
} // Else attempt to claim chunk failed, so try again.
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -26,9 +26,11 @@
#define SHARE_GC_SHARED_PRETOUCH_HPP
#include "gc/shared/workerThread.hpp"
#include "runtime/atomic.hpp"
#include "utilities/globalDefinitions.hpp"
class PretouchTask : public WorkerTask {
char* volatile _cur_addr;
Atomic<char*> _cur_addr;
char* const _end_addr;
size_t _page_size;
size_t _chunk_size;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -30,7 +30,7 @@
uint SuspendibleThreadSet::_nthreads = 0;
uint SuspendibleThreadSet::_nthreads_stopped = 0;
volatile bool SuspendibleThreadSet::_suspend_all = false;
Atomic<bool> SuspendibleThreadSet::_suspend_all{false};
double SuspendibleThreadSet::_suspend_all_start = 0.0;
static Semaphore* _synchronize_wakeup = nullptr;
@ -96,7 +96,7 @@ void SuspendibleThreadSet::synchronize() {
{
MonitorLocker ml(STS_lock, Mutex::_no_safepoint_check_flag);
assert(!should_yield(), "Only one at a time");
AtomicAccess::store(&_suspend_all, true);
_suspend_all.store_relaxed(true);
if (is_synchronized()) {
return;
}
@ -127,6 +127,6 @@ void SuspendibleThreadSet::desynchronize() {
MonitorLocker ml(STS_lock, Mutex::_no_safepoint_check_flag);
assert(should_yield(), "STS not synchronizing");
assert(is_synchronized(), "STS not synchronized");
AtomicAccess::store(&_suspend_all, false);
_suspend_all.store_relaxed(false);
ml.notify_all();
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -26,7 +26,7 @@
#define SHARE_GC_SHARED_SUSPENDIBLETHREADSET_HPP
#include "memory/allocation.hpp"
#include "runtime/atomicAccess.hpp"
#include "runtime/atomic.hpp"
// A SuspendibleThreadSet is a set of threads that can be suspended.
// A thread can join and later leave the set, and periodically yield.
@ -43,7 +43,7 @@ class SuspendibleThreadSet : public AllStatic {
private:
static uint _nthreads;
static uint _nthreads_stopped;
static volatile bool _suspend_all;
static Atomic<bool> _suspend_all;
static double _suspend_all_start;
static bool is_synchronized();
@ -59,7 +59,7 @@ private:
public:
// Returns true if an suspension is in progress.
static bool should_yield() { return AtomicAccess::load(&_suspend_all); }
static bool should_yield() { return _suspend_all.load_relaxed(); }
// Suspends the current thread if a suspension is in progress.
static void yield() {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -42,7 +42,7 @@ WorkerTaskDispatcher::WorkerTaskDispatcher() :
void WorkerTaskDispatcher::coordinator_distribute_task(WorkerTask* task, uint num_workers) {
// No workers are allowed to read the state variables until they have been signaled.
_task = task;
_not_finished = num_workers;
_not_finished.store_relaxed(num_workers);
// Dispatch 'num_workers' number of tasks.
_start_semaphore.signal(num_workers);
@ -51,9 +51,12 @@ void WorkerTaskDispatcher::coordinator_distribute_task(WorkerTask* task, uint nu
_end_semaphore.wait();
// No workers are allowed to read the state variables after the coordinator has been signaled.
assert(_not_finished == 0, "%d not finished workers?", _not_finished);
#ifdef ASSERT
uint not_finished = _not_finished.load_relaxed();
assert(not_finished == 0, "%u not finished workers?", not_finished);
#endif // ASSERT
_task = nullptr;
_started = 0;
_started.store_relaxed(0);
}
void WorkerTaskDispatcher::worker_run_task() {
@ -61,7 +64,7 @@ void WorkerTaskDispatcher::worker_run_task() {
_start_semaphore.wait();
// Get and set worker id.
const uint worker_id = AtomicAccess::fetch_then_add(&_started, 1u);
const uint worker_id = _started.fetch_then_add(1u);
WorkerThread::set_worker_id(worker_id);
// Run task.
@ -70,7 +73,7 @@ void WorkerTaskDispatcher::worker_run_task() {
// Mark that the worker is done with the task.
// The worker is not allowed to read the state variables after this line.
const uint not_finished = AtomicAccess::sub(&_not_finished, 1u);
const uint not_finished = _not_finished.sub_then_fetch(1u);
// The last worker signals to the coordinator that all work is completed.
if (not_finished == 0) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -27,6 +27,7 @@
#include "gc/shared/gcId.hpp"
#include "memory/allocation.hpp"
#include "runtime/atomic.hpp"
#include "runtime/nonJavaThread.hpp"
#include "runtime/semaphore.hpp"
#include "utilities/debug.hpp"
@ -58,8 +59,8 @@ class WorkerTaskDispatcher {
// The task currently being dispatched to the WorkerThreads.
WorkerTask* _task;
volatile uint _started;
volatile uint _not_finished;
Atomic<uint> _started;
Atomic<uint> _not_finished;
// Semaphore used to start the WorkerThreads.
Semaphore _start_semaphore;

View File

@ -183,8 +183,8 @@ void ShenandoahAdaptiveHeuristics::record_success_concurrent() {
}
}
void ShenandoahAdaptiveHeuristics::record_success_degenerated() {
ShenandoahHeuristics::record_success_degenerated();
void ShenandoahAdaptiveHeuristics::record_degenerated() {
ShenandoahHeuristics::record_degenerated();
// Adjust both trigger's parameters in the case of a degenerated GC because
// either of them should have triggered earlier to avoid this case.
adjust_margin_of_error(DEGENERATE_PENALTY_SD);

View File

@ -114,7 +114,7 @@ public:
virtual void record_cycle_start() override;
virtual void record_success_concurrent() override;
virtual void record_success_degenerated() override;
virtual void record_degenerated() override;
virtual void record_success_full() override;
virtual bool should_start_gc() override;

View File

@ -244,7 +244,7 @@ void ShenandoahHeuristics::record_success_concurrent() {
adjust_penalty(Concurrent_Adjust);
}
void ShenandoahHeuristics::record_success_degenerated() {
void ShenandoahHeuristics::record_degenerated() {
adjust_penalty(Degenerated_Penalty);
}

View File

@ -218,7 +218,7 @@ public:
virtual void record_success_concurrent();
virtual void record_success_degenerated();
virtual void record_degenerated();
virtual void record_success_full();

View File

@ -766,10 +766,10 @@ void ShenandoahOldHeuristics::record_success_concurrent() {
this->ShenandoahHeuristics::record_success_concurrent();
}
void ShenandoahOldHeuristics::record_success_degenerated() {
void ShenandoahOldHeuristics::record_degenerated() {
// Forget any triggers that occurred while OLD GC was ongoing. If we really need to start another, it will retrigger.
clear_triggers();
this->ShenandoahHeuristics::record_success_degenerated();
this->ShenandoahHeuristics::record_degenerated();
}
void ShenandoahOldHeuristics::record_success_full() {

View File

@ -201,7 +201,7 @@ public:
void record_success_concurrent() override;
void record_success_degenerated() override;
void record_degenerated() override;
void record_success_full() override;

View File

@ -313,8 +313,12 @@ void ShenandoahDegenGC::op_degenerated() {
policy->record_degenerated(_generation->is_young(), _abbreviated, progress);
if (progress) {
heap->notify_gc_progress();
_generation->heuristics()->record_degenerated();
} else if (!heap->mode()->is_generational() || policy->generational_should_upgrade_degenerated_gc()) {
// Upgrade to full GC, register full-GC impact on heuristics.
op_degenerated_futile();
} else {
_generation->heuristics()->record_degenerated();
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1994, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1994, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -2378,6 +2378,20 @@ public final class Math {
*/
@IntrinsicCandidate
public static double fma(double a, double b, double c) {
// Implementation note: this method is intentionally coded in
// a straightforward manner relying on BigDecimal for the
// heavy-lifting of the numerical computation. It would be
// possible for the computation to be done solely using binary
// floating-point and integer operations, at the cost of more
// complicated logic. Since most processors have hardware
// support for fma and this method is an intrinsic candidate,
// the software implementation below would only be used on
// processors without native fma support (and also possibly on
// processors with native fma support while running in the
// interpreter). Therefore, the direct performance of the code
// is less of a concern than the code's simplicity,
// maintainability, and testability.
/*
* Infinity and NaN arithmetic is not quite the same with two
* roundings as opposed to just one so the simple expression
@ -2492,6 +2506,8 @@ public final class Math {
*/
@IntrinsicCandidate
public static float fma(float a, float b, float c) {
// See implementation note in fma(double, double, double).
if (Float.isFinite(a) && Float.isFinite(b) && Float.isFinite(c)) {
if (a == 0.0 || b == 0.0) {
return a * b + c; // Handled signed zero cases

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -34,6 +34,7 @@ import java.net.URL;
import java.nio.file.Files;
import java.nio.file.InvalidPathException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
@ -112,7 +113,7 @@ public final class Security {
private static Path currentPath;
private static final Set<Path> activePaths = new HashSet<>();
private static final List<Path> activePaths = new ArrayList<>();
static void loadAll() {
// first load the master properties file to
@ -262,30 +263,40 @@ public final class Security {
}
}
private static void checkCyclicInclude(Path path) {
for (Path activePath : activePaths) {
try {
if (Files.isSameFile(path, activePath)) {
throw new InternalError(
"Cyclic include of '" + path + "'");
}
} catch (IOException e) {
if (sdebug != null) {
sdebug.println("skipped exception when checking for " +
"cyclic inclusion of " + path + ":");
e.printStackTrace();
}
}
}
}
private static void loadFromPath(Path path, LoadingMode mode)
throws IOException {
boolean isRegularFile = Files.isRegularFile(path);
if (isRegularFile) {
path = path.toRealPath();
} else if (Files.isDirectory(path)) {
if (Files.isDirectory(path)) {
throw new IOException("Is a directory");
} else {
path = path.toAbsolutePath();
}
if (activePaths.contains(path)) {
throw new InternalError("Cyclic include of '" + path + "'");
}
try (InputStream is = Files.newInputStream(path)) {
checkCyclicInclude(path);
reset(mode);
Path previousPath = currentPath;
currentPath = isRegularFile ? path : null;
currentPath = Files.isRegularFile(path) ? path : null;
activePaths.add(path);
try {
debugLoad(true, path);
props.load(is);
debugLoad(false, path);
} finally {
activePaths.remove(path);
activePaths.removeLast();
currentPath = previousPath;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -241,7 +241,7 @@ public final class ByteArray {
* @param offset where setting (writing) in the array should begin
* @param value value to set in the array
* @throws IndexOutOfBoundsException if the provided {@code offset} is outside
* the range [0, array.length]
* the range [0, array.length - 1]
* @see #getBoolean(byte[], int)
*/
public static void setBoolean(byte[] array, int offset, boolean value) {
@ -328,7 +328,7 @@ public final class ByteArray {
* @param offset where setting (writing) in the array should begin
* @param value value to set in the array
* @throws IndexOutOfBoundsException if the provided {@code offset} is outside
* the range [0, array.length - 2]
* the range [0, array.length - 4]
* @see #getFloat(byte[], int)
*/
public static void setFloat(byte[] array, int offset, float value) {
@ -350,7 +350,7 @@ public final class ByteArray {
* @param offset where setting (writing) in the array should begin
* @param value value to set in the array
* @throws IndexOutOfBoundsException if the provided {@code offset} is outside
* the range [0, array.length - 2]
* the range [0, array.length - 4]
* @see #getFloatRaw(byte[], int)
*/
public static void setFloatRaw(byte[] array, int offset, float value) {
@ -368,7 +368,7 @@ public final class ByteArray {
* @param offset where setting (writing) in the array should begin
* @param value value to set in the array
* @throws IndexOutOfBoundsException if the provided {@code offset} is outside
* the range [0, array.length - 4]
* the range [0, array.length - 8]
* @see #getLong(byte[], int)
*/
public static void setLong(byte[] array, int offset, long value) {
@ -387,7 +387,7 @@ public final class ByteArray {
* @param offset where setting (writing) in the array should begin
* @param value value to set in the array
* @throws IndexOutOfBoundsException if the provided {@code offset} is outside
* the range [0, array.length - 2]
* the range [0, array.length - 8]
* @see #getDouble(byte[], int)
*/
public static void setDouble(byte[] array, int offset, double value) {
@ -409,7 +409,7 @@ public final class ByteArray {
* @param offset where setting (writing) in the array should begin
* @param value value to set in the array
* @throws IndexOutOfBoundsException if the provided {@code offset} is outside
* the range [0, array.length - 2]
* the range [0, array.length - 8]
* @see #getDoubleRaw(byte[], int)
*/
public static void setDoubleRaw(byte[] array, int offset, double value) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -241,7 +241,7 @@ public final class ByteArrayLittleEndian {
* @param offset where setting (writing) in the array should begin
* @param value value to set in the array
* @throws IndexOutOfBoundsException if the provided {@code offset} is outside
* the range [0, array.length]
* the range [0, array.length - 1]
* @see #getBoolean(byte[], int)
*/
public static void setBoolean(byte[] array, int offset, boolean value) {
@ -328,7 +328,7 @@ public final class ByteArrayLittleEndian {
* @param offset where setting (writing) in the array should begin
* @param value value to set in the array
* @throws IndexOutOfBoundsException if the provided {@code offset} is outside
* the range [0, array.length - 2]
* the range [0, array.length - 4]
* @see #getFloat(byte[], int)
*/
public static void setFloat(byte[] array, int offset, float value) {
@ -350,7 +350,7 @@ public final class ByteArrayLittleEndian {
* @param offset where setting (writing) in the array should begin
* @param value value to set in the array
* @throws IndexOutOfBoundsException if the provided {@code offset} is outside
* the range [0, array.length - 2]
* the range [0, array.length - 4]
* @see #getFloatRaw(byte[], int)
*/
public static void setFloatRaw(byte[] array, int offset, float value) {
@ -368,7 +368,7 @@ public final class ByteArrayLittleEndian {
* @param offset where setting (writing) in the array should begin
* @param value value to set in the array
* @throws IndexOutOfBoundsException if the provided {@code offset} is outside
* the range [0, array.length - 4]
* the range [0, array.length - 8]
* @see #getLong(byte[], int)
*/
public static void setLong(byte[] array, int offset, long value) {
@ -387,7 +387,7 @@ public final class ByteArrayLittleEndian {
* @param offset where setting (writing) in the array should begin
* @param value value to set in the array
* @throws IndexOutOfBoundsException if the provided {@code offset} is outside
* the range [0, array.length - 2]
* the range [0, array.length - 8]
* @see #getDouble(byte[], int)
*/
public static void setDouble(byte[] array, int offset, double value) {
@ -409,7 +409,7 @@ public final class ByteArrayLittleEndian {
* @param offset where setting (writing) in the array should begin
* @param value value to set in the array
* @throws IndexOutOfBoundsException if the provided {@code offset} is outside
* the range [0, array.length - 2]
* the range [0, array.length - 8]
* @see #getDoubleRaw(byte[], int)
*/
public static void setDoubleRaw(byte[] array, int offset, double value) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -83,6 +83,22 @@ enum CADistrustPolicy {
}
CamerfirmaTLSPolicy.checkDistrust(chain);
}
},
/**
* Distrust TLS Server certificates anchored by the Chunghwa ePKI root CA
* and issued after March 17, 2026. If enabled, this policy is currently
* enforced by the PKIX and SunX509 TrustManager implementations
* of the SunJSSE provider implementation.
*/
CHUNGHWA_TLS {
void checkDistrust(String variant, X509Certificate[] chain)
throws ValidatorException {
if (!variant.equals(Validator.VAR_TLS_SERVER)) {
return;
}
ChunghwaTLSPolicy.checkDistrust(chain);
}
};
/**

View File

@ -0,0 +1,103 @@
/*
* Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 sun.security.validator;
import java.security.cert.X509Certificate;
import java.time.LocalDate;
import java.time.Month;
import java.time.ZoneOffset;
import java.util.Date;
import java.util.Map;
import java.util.Set;
import sun.security.util.Debug;
import sun.security.x509.X509CertImpl;
/**
* This class checks if Chunghwa issued TLS Server certificates should be
* restricted.
*/
final class ChunghwaTLSPolicy {
private static final Debug debug = Debug.getInstance("certpath");
// SHA-256 certificate fingerprint of distrusted root for TLS
// cacerts alias: chunghwaepkirootca
// DN: OU=ePKI Root Certification Authority,
// O="Chunghwa Telecom Co., Ltd.", C=TW
private static final String FINGERPRINT =
"C0A6F4DC63A24BFDCF54EF2A6A082A0A72DE35803E2FF5FF527AE5D87206DFD5";
// Any TLS Server certificate that is anchored by the Chunghwa
// root above and is issued after this date will be distrusted.
private static final LocalDate MARCH_17_2026 =
LocalDate.of(2026, Month.MARCH, 17);
/**
* This method assumes the eeCert is a TLS Server Cert and chains back to
* the anchor.
*
* @param chain the end-entity's certificate chain. The end entity cert
* is at index 0, the trust anchor at index n-1.
* @throws ValidatorException if the certificate is distrusted
*/
static void checkDistrust(X509Certificate[] chain)
throws ValidatorException {
X509Certificate anchor = chain[chain.length-1];
String fp = fingerprint(anchor);
if (fp == null) {
throw new ValidatorException("Cannot generate fingerprint for "
+ "trust anchor of TLS server certificate");
}
if (FINGERPRINT.equalsIgnoreCase(fp)) {
Date notBefore = chain[0].getNotBefore();
LocalDate ldNotBefore = LocalDate.ofInstant(notBefore.toInstant(),
ZoneOffset.UTC);
// reject if certificate is issued after March 17, 2026
checkNotBefore(ldNotBefore, MARCH_17_2026, anchor);
}
}
private static String fingerprint(X509Certificate cert) {
return X509CertImpl.getFingerprint("SHA-256", cert, debug);
}
// Check whether the certificate's notBeforeDate is after the
// distrust date for the anchor (root CA). Throw ValidatorException
// if it is after the distrust date.
private static void checkNotBefore(LocalDate notBeforeDate,
LocalDate distrustDate, X509Certificate anchor)
throws ValidatorException {
if (notBeforeDate.isAfter(distrustDate)) {
throw new ValidatorException
("TLS Server certificate issued after " + distrustDate +
" and anchored by a distrusted legacy Chunghwa root CA: "
+ anchor.getSubjectX500Principal(),
ValidatorException.T_UNTRUSTED_CERT, anchor);
}
}
private ChunghwaTLSPolicy() {}
}

View File

@ -1437,6 +1437,9 @@ jdk.sasl.disabledMechanisms=
# CAMERFIRMA_TLS : Distrust TLS Server certificates anchored by
# a Camerfirma root CA and issued after April 15, 2025.
#
# CHUNGHWA_TLS : Distrust TLS Server certificates anchored by
# a Chunghwa root CA and issued after March 17, 2026.
#
# Leading and trailing whitespace surrounding each value are ignored.
# Unknown values are ignored. If the property is commented out or set to the
# empty String, no policies are enforced.
@ -1448,7 +1451,8 @@ jdk.sasl.disabledMechanisms=
# jdk.certpath.disabledAlgorithms; those restrictions are still enforced even
# if this property is not enabled.
#
jdk.security.caDistrustPolicies=SYMANTEC_TLS,ENTRUST_TLS,CAMERFIRMA_TLS
jdk.security.caDistrustPolicies=SYMANTEC_TLS,ENTRUST_TLS,CAMERFIRMA_TLS,\
CHUNGHWA_TLS
#
# FilePermission path canonicalization

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -27,6 +27,7 @@
#include "jvm.h"
#include "io_util.h"
#include "io_util_md.h"
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
@ -75,20 +76,26 @@ FD
handleOpen(const char *path, int oflag, int mode) {
FD fd;
RESTARTABLE(open(path, oflag, mode), fd);
if (fd != -1) {
struct stat buf;
int result;
RESTARTABLE(fstat(fd, &buf), result);
if (result != -1) {
if (S_ISDIR(buf.st_mode)) {
close(fd);
errno = EISDIR;
fd = -1;
}
} else {
// No further checking is needed if the file is not a
// directory or open returned an error
if (fd == -1 || ((oflag & O_ACCMODE) != O_RDONLY) != 0) {
return fd;
}
// FileInputStream is specified to throw if the
// file is a directory
struct stat buf;
int result;
RESTARTABLE(fstat(fd, &buf), result);
if (result != -1) {
if (S_ISDIR(buf.st_mode)) {
close(fd);
errno = EISDIR;
fd = -1;
}
} else {
close(fd);
fd = -1;
}
return fd;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -37,6 +37,13 @@ import javax.lang.model.type.*;
* clause, among other restrictions; see JLS {@jls 9.6.1} for details.
*
* @see ExecutableType
* @jls 8.4 Method Declarations
* @jls 8.6 Instance Initializers
* @jls 8.7 Static Initializers
* @jls 8.8 Constructor Declarations
* @jls 9.4 Method Declarations
* @jls 9.6.1 Annotation Interface Elements
*
* @since 1.6
*/
public interface ExecutableElement extends Element, Parameterizable {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -58,6 +58,8 @@ import javax.lang.model.type.TypeMirror;
* </ul>
*
* @see javax.lang.model.util.Elements#getPackageOf
* @jls 7.4 Package Declarations
*
* @since 1.6
*/
public interface PackageElement extends Element, QualifiedNameable {
@ -87,6 +89,7 @@ public interface PackageElement extends Element, QualifiedNameable {
* @return the fully qualified name of this package, or an
* empty name if this is an unnamed package
* @jls 6.7 Fully Qualified Names and Canonical Names
* @jls 7.4.1 Named Packages
*/
Name getQualifiedName();

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2009, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2009, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -30,6 +30,10 @@ import java.util.List;
/**
* A mixin interface for an element that has type parameters.
*
* @jls 4.5 Parameterized Types
* @jls 8.4.4 Generic Methods
* @jls 8.8.4 Generic Constructors
*
* @since 1.7
*/
public interface Parameterizable extends Element {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2009, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2009, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -28,6 +28,10 @@ package javax.lang.model.element;
/**
* A mixin interface for an element that has a qualified name.
*
* @jls 6.5.3.2 Qualified Package Names
* @jls 6.5.5.2 Qualified Type Names
* @jls 6.7 Fully Qualified Names and Canonical Names
*
* @since 1.7
*/
public interface QualifiedNameable extends Element {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -80,7 +80,16 @@ import javax.lang.model.util.*;
* javax.lang.model.util.Elements#getAllTypeElements(CharSequence)
* queried for} in the configured environment
* </ul>
*
* @see DeclaredType
* @jls 8.1 Class Declarations
* @jls 8.5 Member Class and Interface Declarations
* @jls 8.9 Enum Classes
* @jls 8.10 Record Classes
* @jls 9.1 Interface Declarations
* @jls 9.5 Member Class and Interface Declarations
* @jls 9.6 Annotation Interfaces
*
* @since 1.6
*/
public interface TypeElement extends Element, Parameterizable, QualifiedNameable {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -35,6 +35,11 @@ import javax.lang.model.type.TypeVariable;
* A type parameter declares a {@link TypeVariable}.
*
* @see TypeVariable
* @jls 8.1.2 Generic Classes and Type Parameters
* @jls 8.4.4 Generic Methods
* @jls 8.8.4 Generic Constructors
* @jls 9.1.2 Generic Interfaces and Type Parameters
*
* @since 1.6
*/
public interface TypeParameterElement extends Element {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -34,6 +34,14 @@ import javax.lang.model.type.TypeKind;
* parameter, local variable, resource variable, or exception
* parameter.
*
* @jls 8.3 Field Declaration
* @jls 8.9.1 Enum Constants
* @jls 8.4.1 Formal Parameters
* @jls 8.8.1 Formal Parameters
* @jls 14.4 Local Variable Declarations
* @jls 14.20 The {@code try} statement
* @jls 14.20.3 {@code try}-with-resources
* @since 1.6
*/
public interface VariableElement extends Element {

View File

@ -35,8 +35,6 @@ import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.plaf.UIResource;
import sun.awt.AppContext;
import sun.lwawt.macosx.CPlatformWindow;
import sun.swing.SwingUtilities2;
@ -150,13 +148,34 @@ final class AquaUtils {
protected abstract T create();
}
abstract static class RecyclableSingleton<T> {
final T get() {
return AppContext.getSoftReferenceValue(this, () -> getInstance());
}
abstract static class LazySingleton<T> {
T instance;
void reset() {
AppContext.getAppContext().remove(this);
final T get() {
if (instance == null) {
instance = getInstance();
}
return instance;
}
abstract T getInstance();
}
abstract static class RecyclableSingleton<T> {
SoftReference<T> ref;
final T get() {
T instance;
if (ref != null) {
instance = ref.get();
if (instance != null) {
return instance;
}
}
instance = getInstance();
ref = new SoftReference<>(instance);
return instance;
}
abstract T getInstance();
@ -197,11 +216,11 @@ final class AquaUtils {
protected abstract V getInstance(K key);
}
private static final RecyclableSingleton<Boolean> enableAnimations = new RecyclableSingleton<Boolean>() {
private static final LazySingleton<Boolean> enableAnimations = new LazySingleton<Boolean>() {
@Override
protected Boolean getInstance() {
final String sizeProperty = System.getProperty(ANIMATIONS_PROPERTY);
return !"false".equals(sizeProperty); // should be true by default
final String animationsProperty = System.getProperty(ANIMATIONS_PROPERTY);
return !"false".equals(animationsProperty); // should be true by default
}
};
private static boolean animationsEnabled() {

View File

@ -47,7 +47,6 @@ import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Supplier;
/**
* The AppContext is a table referenced by ThreadGroup which stores
@ -735,24 +734,6 @@ public final class AppContext {
}
return changeSupport.getPropertyChangeListeners(propertyName);
}
public static <T> T getSoftReferenceValue(Object key,
Supplier<T> supplier) {
final AppContext appContext = AppContext.getAppContext();
@SuppressWarnings("unchecked")
SoftReference<T> ref = (SoftReference<T>) appContext.get(key);
if (ref != null) {
final T object = ref.get();
if (object != null) {
return object;
}
}
final T object = supplier.get();
ref = new SoftReference<>(object);
appContext.put(key, ref);
return object;
}
}
final class MostRecentKeyValue {

View File

@ -29,7 +29,6 @@ import java.awt.*;
import java.lang.ref.*;
import java.util.*;
import java.util.concurrent.locks.*;
import sun.awt.AppContext;
/**
* ImageCache - A fixed pixel count sized cache of Images keyed by arbitrary
@ -37,8 +36,6 @@ import sun.awt.AppContext;
* dropped by the GC if heap memory gets tight. When our size hits max pixel
* count least recently requested images are removed first.
*
* The ImageCache must be used from the thread with an AppContext only.
*
*/
public final class ImageCache {
@ -56,9 +53,10 @@ public final class ImageCache {
// Reference queue for tracking lost softreferences to images in the cache
private final ReferenceQueue<Image> referenceQueue = new ReferenceQueue<>();
private static final ImageCache instance = new ImageCache();
public static ImageCache getInstance() {
return AppContext.getSoftReferenceValue(ImageCache.class,
() -> new ImageCache());
return instance;
}
ImageCache(final int maxPixelCount) {

View File

@ -37,11 +37,7 @@ import java.util.Set;
import java.util.stream.Stream;
import com.sun.tools.javac.main.Option;
import com.sun.tools.javac.tree.JCTree.*;
import com.sun.tools.javac.util.Assert;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
import com.sun.tools.javac.util.JCDiagnostic.LintWarning;
import com.sun.tools.javac.util.Log;
import com.sun.tools.javac.util.Names;
import com.sun.tools.javac.util.Options;
@ -178,6 +174,14 @@ public class Lint {
/**
* Categories of warnings that can be generated by the compiler.
* Each lint category has a logical name (a string), which is the string used e.g. in a {@code SuppressWarning} annotation.
* To ensure automation, the enum field name for a lint category string {@code C} should be obtained by:
* <ol>
* <li>capitalize all the letters in {@code C}, and</li>
* <li>replacing any occurrence of {@code -} with {@code _}</li>
* </ol>
* For instance, the lint category string {@code dangling-doc-comments} corresponds to the enum field
* {@code DANGLING_DOC_COMMENTS}.
*/
public enum LintCategory {
/**
@ -320,7 +324,7 @@ public class Lint {
/**
* Warn about unchecked operations on raw types.
*/
RAW("rawtypes"),
RAWTYPES("rawtypes"),
/**
* Warn about use of deprecated-for-removal items.

View File

@ -58,7 +58,13 @@ final class Instrumentation {
}
public void addMethod(long methodId, String name, String signature, int modification) {
modificationMap.put(name + signature, new Method(methodId, Modification.valueOf(modification), className + "::" + name));
Method method = new Method(
methodId,
Modification.valueOf(modification),
name.equals("<init>"),
className + "::" + name
);
modificationMap.put(name + signature, method);
}
public List<Method> getMethods() {
@ -71,7 +77,7 @@ final class Instrumentation {
ClassModel classModel = classFile.parse(bytecode);
byte[] generated = classFile.build(classModel.thisClass().asSymbol(), classBuilder -> {
for (var ce : classModel) {
if (modifyClassElement(classBuilder, ce)) {
if (modifyClassElement(classModel, classBuilder, ce)) {
modified[0] = true;
} else {
classBuilder.with(ce);
@ -93,7 +99,7 @@ final class Instrumentation {
}
}
private boolean modifyClassElement(ClassBuilder classBuilder, ClassElement ce) {
private boolean modifyClassElement(ClassModel classModel, ClassBuilder classBuilder, ClassElement ce) {
if (ce instanceof MethodModel mm) {
String method = mm.methodName().stringValue();
String signature = mm.methodType().stringValue();
@ -102,15 +108,15 @@ final class Instrumentation {
if (tm != null) {
Modification m = tm.modification();
if (m.tracing() || m.timing()) {
return modifyMethod(classBuilder, mm, tm);
return modifyMethod(classModel, classBuilder, mm, tm);
}
}
}
return false;
}
private boolean modifyMethod(ClassBuilder classBuilder, MethodModel m, Method method) {
var code = m.code();
private boolean modifyMethod(ClassModel classModel, ClassBuilder classBuilder, MethodModel methodModel, Method method) {
var code = methodModel.code();
if (code.isPresent()) {
if (classLoader == null && ExcludeList.containsMethod(method.name())) {
String msg = "Risk of recursion, skipping bytecode generation of " + method.name();
@ -118,9 +124,9 @@ final class Instrumentation {
return false;
}
MethodTransform s = MethodTransform.ofStateful(
() -> MethodTransform.transformingCode(new Transform(method))
() -> MethodTransform.transformingCode(new Transform(classModel, code.get(), method))
);
classBuilder.transformMethod(m, s);
classBuilder.transformMethod(methodModel, s);
return true;
}
return false;

View File

@ -31,7 +31,7 @@ import jdk.jfr.internal.Logger;
/**
* Class that holds information about an instrumented method.
*/
record Method(long methodId, Modification modification, String name) {
record Method(long methodId, Modification modification, boolean constructor, String name) {
@Override
public String toString() {
return name + (modification.timing() ? " +timing" : " -timing") + (modification.tracing() ? " +tracing" : " -tracing") + " (Method ID: " + String.format("0x%08X)", methodId);

View File

@ -24,13 +24,19 @@
*/
package jdk.jfr.internal.tracing;
import java.lang.classfile.ClassModel;
import java.lang.classfile.CodeBuilder;
import java.lang.classfile.CodeElement;
import java.lang.classfile.CodeModel;
import java.lang.classfile.CodeTransform;
import java.lang.classfile.Label;
import java.lang.classfile.TypeKind;
import java.lang.classfile.instruction.InvokeInstruction;
import java.lang.classfile.instruction.ReturnInstruction;
import java.lang.classfile.instruction.ThrowInstruction;
import java.lang.constant.ClassDesc;
import java.util.ArrayList;
import java.util.List;
import jdk.jfr.internal.util.Bytecode;
import jdk.jfr.internal.util.Bytecode.MethodDesc;
@ -43,59 +49,208 @@ import jdk.jfr.tracing.MethodTracer;
* The method ID is determined by native code.
*/
final class Transform implements CodeTransform {
private static class TryBlock {
Label start;
Label end;
}
private static final ClassDesc METHOD_TRACER_CLASS = ClassDesc.of(MethodTracer.class.getName());
private static final MethodDesc TRACE_METHOD = MethodDesc.of("trace", "(JJ)V");
private static final MethodDesc TIMING_METHOD = MethodDesc.of("timing", "(JJ)V");
private static final MethodDesc TRACE_TIMING_METHOD = MethodDesc.of("traceTiming", "(JJ)V");
private static final MethodDesc TIMESTAMP_METHOD = MethodDesc.of("timestamp", "()J");
private final List<TryBlock> tryBlocks = new ArrayList<>();
private final boolean simplifiedInstrumentation;
private final ClassModel classModel;
private final Method method;
private int timestampSlot = -1;
Transform(Method method) {
Transform(ClassModel classModel, CodeModel model, Method method) {
this.method = method;
this.classModel = classModel;
// The JVMS (not the JLS) allows multiple mutually exclusive super/this.<init>
// invocations in a constructor body as long as only one lies on any given
// execution path. For example, this is valid bytecode:
//
// Foo(boolean value) {
// if (value) {
// staticMethodThatMayThrow();
// super();
// } else {
// try {
// if (value == 0) {
// throw new Exception("");
// }
// } catch (Throwable t) {
// throw t;
// }
// super();
// }
// }
//
// If such a method is found, instrumentation falls back to instrumenting only
// RET and ATHROW. This can cause exceptions to be missed or counted twice.
//
// An effect of this heuristic is that constructors like the one below
// will also trigger simplified instrumentation.
//
// class Bar {
// }
//
// class Foo extends Bar {
// Foo() {
// new Bar();
// }
// }
//
// java.lang.Object::<init> with zero constructor invocations should use simplified instrumentation
this.simplifiedInstrumentation = method.constructor() && constructorInvocations(model.elementList()) != 1;
}
private int constructorInvocations(List<CodeElement> elementList) {
int count = 0;
for (CodeElement e : elementList) {
if (isConstructorInvocation(e)) {
count++;
}
}
return count;
}
private boolean isConstructorInvocation(CodeElement element) {
if (element instanceof InvokeInstruction inv && inv.name().equalsString("<init>")) {
if (classModel.thisClass().equals(inv.owner())) {
return true;
}
if (classModel.superclass().isPresent()) {
return classModel.superclass().get().equals(inv.owner());
}
}
return false;
}
@Override
public final void accept(CodeBuilder builder, CodeElement element) {
public void accept(CodeBuilder builder, CodeElement element) {
if (simplifiedInstrumentation) {
acceptSimplifiedInstrumentation(builder, element);
return;
}
if (method.constructor()) {
acceptConstructor(builder, element, isConstructorInvocation(element));
} else {
acceptMethod(builder, element);
}
}
@Override
public void atEnd(CodeBuilder builder) {
endTryBlock(builder);
for (TryBlock block : tryBlocks) {
addCatchHandler(block, builder);
}
}
private void acceptConstructor(CodeBuilder builder, CodeElement element, boolean isConstructorInvocation) {
if (timestampSlot == -1) {
timestampSlot = invokeTimestamp(builder);
builder.lstore(timestampSlot);
if (!isConstructorInvocation) {
beginTryBlock(builder);
}
}
if (isConstructorInvocation) {
endTryBlock(builder);
builder.with(element);
beginTryBlock(builder);
return;
}
if (element instanceof ReturnInstruction) {
addTracing(builder);
}
builder.with(element);
}
private void endTryBlock(CodeBuilder builder) {
if (tryBlocks.isEmpty()) {
return;
}
TryBlock last = tryBlocks.getLast();
if (last.end == null) {
last.end = builder.newBoundLabel();
}
}
private void beginTryBlock(CodeBuilder builder) {
TryBlock block = new TryBlock();
block.start = builder.newBoundLabel();
tryBlocks.add(block);
}
private void acceptSimplifiedInstrumentation(CodeBuilder builder, CodeElement element) {
if (timestampSlot == -1) {
timestampSlot = invokeTimestamp(builder);
builder.lstore(timestampSlot);
}
if (element instanceof ReturnInstruction || element instanceof ThrowInstruction) {
builder.lload(timestampSlot);
builder.ldc(method.methodId());
Modification modification = method.modification();
boolean objectInit = method.name().equals("java.lang.Object::<init>");
String suffix = objectInit ? "ObjectInit" : "";
if (modification.timing()) {
if (modification.tracing()) {
invokeTraceTiming(builder, suffix);
} else {
invokeTiming(builder, suffix);
}
} else {
if (modification.tracing()) {
invokeTrace(builder, suffix);
}
}
addTracing(builder);
}
builder.with(element);
}
public static void invokeTiming(CodeBuilder builder, String suffix) {
private void acceptMethod(CodeBuilder builder, CodeElement element) {
if (timestampSlot == -1) {
timestampSlot = invokeTimestamp(builder);
builder.lstore(timestampSlot);
beginTryBlock(builder);
}
if (element instanceof ReturnInstruction) {
addTracing(builder);
}
builder.with(element);
}
private void addCatchHandler(TryBlock block, CodeBuilder builder) {
Label catchHandler = builder.newBoundLabel();
int exceptionSlot = builder.allocateLocal(TypeKind.REFERENCE);
builder.astore(exceptionSlot);
addTracing(builder);
builder.aload(exceptionSlot);
builder.athrow();
builder.exceptionCatchAll(block.start, block.end, catchHandler);
}
private void addTracing(CodeBuilder builder) {
builder.lload(timestampSlot);
builder.ldc(method.methodId());
Modification modification = method.modification();
boolean objectInit = method.name().equals("java.lang.Object::<init>");
String suffix = objectInit ? "ObjectInit" : "";
if (modification.timing()) {
if (modification.tracing()) {
invokeTraceTiming(builder, suffix);
} else {
invokeTiming(builder, suffix);
}
} else {
if (modification.tracing()) {
invokeTrace(builder, suffix);
}
}
}
private static void invokeTiming(CodeBuilder builder, String suffix) {
builder.invokestatic(METHOD_TRACER_CLASS, TIMING_METHOD.name() + suffix, TIMING_METHOD.descriptor());
}
public static void invokeTrace(CodeBuilder builder, String suffix) {
private static void invokeTrace(CodeBuilder builder, String suffix) {
builder.invokestatic(METHOD_TRACER_CLASS, TRACE_METHOD.name() + suffix, TRACE_METHOD.descriptor());
}
public static void invokeTraceTiming(CodeBuilder builder, String suffix) {
private static void invokeTraceTiming(CodeBuilder builder, String suffix) {
builder.invokestatic(METHOD_TRACER_CLASS, TRACE_TIMING_METHOD.name() + suffix, TRACE_TIMING_METHOD.descriptor());
}
public static int invokeTimestamp(CodeBuilder builder) {
private static int invokeTimestamp(CodeBuilder builder) {
Bytecode.invokestatic(builder, METHOD_TRACER_CLASS, TIMESTAMP_METHOD);
return builder.allocateLocal(TypeKind.LONG);
}

View File

@ -77,8 +77,6 @@ compiler/interpreter/Test6833129.java 8335266 generic-i586
compiler/c2/aarch64/TestStaticCallStub.java 8359963 linux-aarch64,macosx-aarch64
serviceability/jvmti/NMethodRelocation/NMethodRelocationTest.java 8369150 generic-all
#############################################################################
# :hotspot_gc

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -1052,35 +1052,20 @@ public class TestAliasingFuzzer {
case Aliasing.CONTAINER_DIFFERENT,
Aliasing.CONTAINER_SAME_ALIASING_NEVER,
Aliasing.CONTAINER_UNKNOWN_ALIASING_NEVER ->
// We would have liked to check that there is no multiversioning.
//
// But sadly there are some cases that have issues with RCE and/or
// predicates, and so we end up using multiversioning anyway. We
// should fix those cases eventually, to strengthen the checks here.
//
// The array cases are a little more tame, and do not have the same
// issues as the MemorySegment cases.
(containerKind == ContainerKind.ARRAY)
? """
// Aliasing check should never fail at runtime, so the predicate
// should never fail, and we do not have to use multiversioning.
// Failure could have a few causes:
// - issues with doing RCE / missing predicates
// -> other loop-opts need to be fixed
// - predicate fails: recompile with multiversioning
// -> logic in runtime check may be wrong
@IR(counts = {".*multiversion.*", "= 0"},
phase = CompilePhase.PRINT_IDEAL,
applyIf = {"UseAutoVectorizationPredicate", "true"},
applyIfPlatform = {"64-bit", "true"},
applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"})
"""
: """
// Due to cases like JDK-8360204 and JDK-8365982, there can be issues
// with RCE leading cases where we remove predicates and then unroll again
// and then end up multiversioning. These cases seem relatively rare but
// prevent us from asserting that there is never multiversioning in these cases.
""";
"""
// Aliasing check should never fail at runtime, so the predicate
// should never fail, and we do not have to use multiversioning.
// Failure could have a few causes:
// - issues with doing RCE / missing predicates
// -> other loop-opts need to be fixed
// - predicate fails: recompile with multiversioning
// -> logic in runtime check may be wrong
@IR(counts = {".*multiversion.*", "= 0"},
phase = CompilePhase.PRINT_IDEAL,
applyIf = {"UseAutoVectorizationPredicate", "true"},
applyIfPlatform = {"64-bit", "true"},
applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"})
""";
case Aliasing.CONTAINER_SAME_ALIASING_UNKNOWN,
Aliasing.CONTAINER_UNKNOWN_ALIASING_UNKNOWN ->
"""

View File

@ -116,7 +116,7 @@ public abstract class JVMOption {
default:
throw new Error("Expected only \"int\", \"intx\", \"size_t\", "
+ "\"uint\", \"uintx\", \"uint64_t\", or \"double\" "
+ "option types! Got " + type + " type!");
+ "option types! Got " + type + " type for option " + name + "!");
}
return parameter;

View File

@ -0,0 +1,60 @@
/*
* Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
/*
* @test
* @bug 8374639
* @requires vm.cds.supports.aot.class.linking
* @library /test/lib
* @build DynamicDumpWithAOTLinkedStaticArchive jdk.test.whitebox.WhiteBox
* @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
* @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar TestApp
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. DynamicDumpWithAOTLinkedStaticArchive
*/
import jdk.test.lib.cds.SimpleCDSAppTester;
import jdk.test.lib.process.OutputAnalyzer;
public class DynamicDumpWithAOTLinkedStaticArchive {
public static void main(String... args) throws Exception {
SimpleCDSAppTester.of("DynamicDumpWithAOTLinkedStaticArchive")
.classpath("app.jar")
.appCommandLine("TestApp")
.setGenerateBaseArchive(true)
.setBaseArchiveOptions("-XX:+AOTClassLinking")
.setProductionChecker((OutputAnalyzer out) -> {
out.shouldContain("HelloWorld");
})
.runDynamicWorkflow();
}
}
class TestApp {
public static void main(String[] args) {
System.out.println("HelloWorld");
System[][][] x = new System[0][0][0];
System.out.println(x);
}
}

View File

@ -1,170 +0,0 @@
/*
* Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
/*
* @test
* @summary handling of the existence of InstanceKlass::array_klasses()
* @requires vm.cds
* @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds
* /test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes
* @build ArrayKlassesApp
* @build jdk.test.whitebox.WhiteBox
* @run driver jdk.test.lib.helpers.ClassFileInstaller -jar ArrayKlasses.jar ArrayKlassesApp
* @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. ArrayKlasses
*/
import jdk.test.lib.helpers.ClassFileInstaller;
public class ArrayKlasses extends DynamicArchiveTestBase {
public static void main(String[] args) throws Exception {
runTest(ArrayKlasses::test);
}
static void test() throws Exception {
String topArchiveName = getNewArchiveName();
final String appJar = ClassFileInstaller.getJarPath("ArrayKlasses.jar");
final String mainClass = "ArrayKlassesApp";
final String runtimeLogOptions =
"-Xlog:class+load,class+load+array=debug,cds+dynamic=debug,cds=debug,aot+unshareable=trace";
// Case 1
// Create a dynamic archive with the ArrayKlassesApp app class and its
// array classes.
dump2(null, topArchiveName,
"-Xlog:cds+dynamic=debug,cds+class=debug",
"-cp", appJar, mainClass)
.assertNormalExit(output -> {
output.shouldMatch("cds.class.*klasses.*array \\[LArrayKlassesApp;")
.shouldMatch("cds.class.*klasses.*array \\[\\[LArrayKlassesApp;")
.shouldMatch("cds.class.*klasses.*array \\[\\[\\[LArrayKlassesApp;");
});
// Case 1
// At runtime , the ArrayKlasesApp and its array class should be loaded
// from the dynamic archive.
run2(null, topArchiveName, runtimeLogOptions,
"-cp", appJar, mainClass)
.assertNormalExit(output -> {
output.shouldContain("ArrayKlassesApp source: shared objects file (top)")
.shouldContain("restore: ArrayKlassesApp with class loader: jdk.internal.loader.ClassLoaders$AppClassLoader")
.shouldContain("[LArrayKlassesApp; source: shared objects file (top)")
.shouldContain("restore: [LArrayKlassesApp; with class loader: jdk.internal.loader.ClassLoaders$AppClassLoader")
.shouldContain("[[LArrayKlassesApp; source: shared objects file (top)")
.shouldContain("restore: [[LArrayKlassesApp; with class loader: jdk.internal.loader.ClassLoaders$AppClassLoader")
.shouldContain("[[[LArrayKlassesApp; source: shared objects file (top)")
.shouldContain("restore: [[[LArrayKlassesApp; with class loader: jdk.internal.loader.ClassLoaders$AppClassLoader")
.shouldHaveExitValue(0);
});
// Case 2
// Create a dynamic archive with the array classes of java/util/Date which
// is in the default CDS archive.
topArchiveName = getNewArchiveName();
dump2(null, topArchiveName,
"-Xlog:class+load,cds+dynamic=debug,cds+class=debug",
"-cp", appJar, mainClass, "system")
.assertNormalExit(output -> {
output.shouldContain("java.util.Date source: shared objects file")
.shouldMatch("cds.class.*klasses.*array \\[Ljava.util.Date;")
.shouldMatch("cds.class.*klasses.*array \\[\\[Ljava.util.Date;")
.shouldMatch("cds.class.*klasses.*array \\[\\[\\[Ljava.util.Date;");
});
// Case 2
// At runtime, the java/util/Date class should be loaded from the default
// CDS archive; its array class should be loaded from the dynamic archive.
run2(null, topArchiveName, runtimeLogOptions,
"-cp", appJar, mainClass, "system")
.assertNormalExit(output -> {
output.shouldContain("java.util.Date source: shared objects file")
.shouldContain("restore: java.util.Date with class loader: boot")
.shouldContain("[Ljava.util.Date; source: shared objects file (top)")
.shouldContain("restore: [Ljava.util.Date; with class loader: boot")
.shouldContain("[[Ljava.util.Date; source: shared objects file (top)")
.shouldContain("restore: [[Ljava.util.Date; with class loader: boot")
.shouldContain("[[[Ljava.util.Date; source: shared objects file (top)")
.shouldContain("restore: [[[Ljava.util.Date; with class loader: boot")
.shouldHaveExitValue(0);
});
// Case 3
// Create a dynamic archive with primitive arrays [[J and [[[J with [J
// already in the default CDS archive
topArchiveName = getNewArchiveName();
dump2(null, topArchiveName,
"-Xlog:class+load,cds+dynamic=debug,cds+class=debug",
"-cp", appJar, mainClass, "primitive")
.assertNormalExit(output -> {
output.shouldMatch("cds.class.*klasses.*array \\[\\[J")
.shouldMatch("cds.class.*klasses.*array \\[\\[\\[J");
});
// Case 3
// At runtime, the [J should be loaded from the default CDS archive;
// the higher-dimension array should be loaded from the dynamic archive.
run2(null, topArchiveName, runtimeLogOptions,
"-cp", appJar, mainClass, "primitive")
.assertNormalExit(output -> {
output.shouldContain("[J source: shared objects file")
.shouldContain("restore: [J with class loader: boot")
.shouldContain("[[J source: shared objects file (top)")
.shouldContain("restore: [[J with class loader: boot")
.shouldContain("[[[J source: shared objects file (top)")
.shouldContain("restore: [[[J with class loader: boot")
.shouldHaveExitValue(0);
});
// Case 4
// Create a dynamic archive with 2-, 3- and 4-dimension arrays of java/lang/Integer.
// The java/lang/Integer class and the 1-dimension array is in the default archive.
topArchiveName = getNewArchiveName();
dump2(null, topArchiveName,
"-Xlog:class+load,cds+dynamic=debug,cds+class=debug",
"-cp", appJar, mainClass, "integer-array")
.assertNormalExit(output -> {
output.shouldMatch("cds.class.*klasses.*array \\[\\[Ljava.lang.Integer;")
.shouldMatch("cds.class.*klasses.*array \\[\\[\\[Ljava.lang.Integer;")
.shouldMatch("cds.class.*klasses.*array \\[\\[\\[\\[Ljava.lang.Integer;");
});
// Case 4
// At runtime, the 4-dimension array of java/lang/Integer should be
// loaded from the dynamic archive.
run2(null, topArchiveName, runtimeLogOptions,
"-cp", appJar, mainClass, "integer-array")
.assertNormalExit(output -> {
output.shouldContain("java.lang.Integer source: shared objects file")
.shouldContain("restore: java.lang.Integer with class loader: boot")
.shouldContain("restore: [Ljava.lang.Integer; with class loader: boot")
.shouldContain("[[Ljava.lang.Integer; source: shared objects file (top)")
.shouldContain("restore: [[Ljava.lang.Integer; with class loader: boot")
.shouldContain("[[[Ljava.lang.Integer; source: shared objects file (top)")
.shouldContain("restore: [[[Ljava.lang.Integer; with class loader: boot")
.shouldContain("[[[[Ljava.lang.Integer; source: shared objects file (top)")
.shouldContain("restore: [[[[Ljava.lang.Integer; with class loader: boot")
.shouldHaveExitValue(0);
});
}
}

View File

@ -1,77 +0,0 @@
/*
* Copyright (c) 2019, 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.lang.reflect.Array;
import java.util.Date;
public class ArrayKlassesApp {
public static void main(String args[]) {
if (args.length == 1) {
if (args[0].equals("system")) {
Date[][][] array = new Date[1][2][2];
int count = 0;
for (int i=0; i<1; i++) {
for (int j=0; j<2; j++) {
for (int k=0; k<2; k++) {
array[i][j][k] = new Date();
count++;
array[i][j][k].setTime(20000 * count);
}
}
}
} else if (args[0].equals("primitive")) {
long[][][] larray = new long[1][2][2];
long lcount = 0;
for (int i=0; i<1; i++) {
for (int j=0; j<2; j++) {
for (int k=0; k<2; k++) {
lcount++;
larray[i][j][k] = lcount;
}
}
}
} else if (args[0].equals("integer-array")) {
Integer[][][][] iarray = new Integer[4][4][4][4];
int count = 0;
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
for (int k = 0; k < 4; k++) {
for (int l = 0; l < 4; l++) {
count++;
iarray[i][j][k][l] = new Integer(count);
}
}
}
}
System.out.println(iarray);
System.out.println(iarray.getClass());
}
} else {
Object x = Array.newInstance(ArrayKlassesApp.class, 3,3,3);
System.out.println(x);
System.out.println(x.getClass());
System.out.println(Array.getLength(x));
}
}
}

View File

@ -23,23 +23,30 @@
/*
* @test
*
* @bug 8316694
* @summary Verify that nmethod relocation posts the correct JVMTI events
* @requires vm.jvmti
* @requires vm.gc == "null" | vm.gc == "Serial"
* @requires vm.jvmti &
* vm.gc != "Epsilon" &
* vm.flavor == "server" &
* !vm.emulatedClient &
* (vm.opt.TieredStopAtLevel == null | vm.opt.TieredStopAtLevel == 4)
* @library /test/lib /test/hotspot/jtreg
* @build jdk.test.whitebox.WhiteBox
* @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
* @run main/othervm/native NMethodRelocationTest
* @run main/othervm/native -agentlib:NMethodRelocationTest
* --enable-native-access=ALL-UNNAMED
* -Xbootclasspath/a:.
* -Xbatch
* -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI
* -XX:+SegmentedCodeCache
* -XX:-TieredCompilation
* -XX:+UnlockExperimentalVMOptions
* -XX:+NMethodRelocation
* NMethodRelocationTest
*/
import static compiler.whitebox.CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION;
import java.lang.reflect.Executable;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import jdk.test.lib.Asserts;
import jdk.test.lib.process.OutputAnalyzer;
@ -48,52 +55,9 @@ import jdk.test.whitebox.WhiteBox;
import jdk.test.whitebox.code.BlobType;
import jdk.test.whitebox.code.NMethod;
import static compiler.whitebox.CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION;
public class NMethodRelocationTest {
public static void main(String[] args) throws Exception {
ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder(
"-agentlib:NMethodRelocationTest",
"--enable-native-access=ALL-UNNAMED",
"-Xbootclasspath/a:.",
"-XX:+UseSerialGC",
"-XX:+UnlockDiagnosticVMOptions",
"-XX:+WhiteBoxAPI",
"-XX:+SegmentedCodeCache",
"-XX:-TieredCompilation",
"-XX:+UnlockExperimentalVMOptions",
"-XX:+NMethodRelocation",
"DoWork");
OutputAnalyzer oa = new OutputAnalyzer(pb.start());
String output = oa.getOutput();
if (oa.getExitValue() != 0) {
System.err.println(oa.getOutput());
throw new RuntimeException("Non-zero exit code returned from the test");
}
Asserts.assertTrue(oa.getExitValue() == 0);
Pattern pattern = Pattern.compile("(?m)^Relocated nmethod from (0x[0-9a-f]{16}) to (0x[0-9a-f]{16})$");
Matcher matcher = pattern.matcher(output);
if (matcher.find()) {
String fromAddr = matcher.group(1);
String toAddr = matcher.group(2);
// Confirm events sent for both original and relocated nmethod
oa.shouldContain("<COMPILED_METHOD_LOAD>: name: compiledMethod, code: " + fromAddr);
oa.shouldContain("<COMPILED_METHOD_LOAD>: name: compiledMethod, code: " + toAddr);
oa.shouldContain("<COMPILED_METHOD_UNLOAD>: name: compiledMethod, code: " + fromAddr);
oa.shouldContain("<COMPILED_METHOD_UNLOAD>: name: compiledMethod, code: " + toAddr);
} else {
System.err.println(oa.getOutput());
throw new RuntimeException("Unable to find relocation information");
}
}
}
class DoWork {
protected static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
/** Load native library if required. */
static {
@ -107,43 +71,18 @@ class DoWork {
}
}
/**
* Returns value of VM option.
*
* @param name option's name
* @return value of option or {@code null}, if option doesn't exist
* @throws NullPointerException if name is null
*/
protected static String getVMOption(String name) {
Objects.requireNonNull(name);
return Objects.toString(WHITE_BOX.getVMFlag(name), null);
}
protected static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
/**
* Returns value of VM option or default value.
*
* @param name option's name
* @param defaultValue default value
* @return value of option or {@code defaultValue}, if option doesn't exist
* @throws NullPointerException if name is null
* @see #getVMOption(String)
*/
protected static String getVMOption(String name, String defaultValue) {
String result = getVMOption(name);
return result == null ? defaultValue : result;
}
native static boolean shouldExit();
public static void main(String argv[]) throws Exception {
run();
}
public static void run() throws Exception {
Executable method = DoWork.class.getDeclaredMethod("compiledMethod");
public static void main(String[] argv) throws Exception {
Executable method = NMethodRelocationTest.class.getDeclaredMethod("compiledMethod");
WHITE_BOX.testSetDontInlineMethod(method, true);
WHITE_BOX.enqueueMethodForCompilation(method, COMP_LEVEL_FULL_OPTIMIZATION);
while (WHITE_BOX.isMethodQueuedForCompilation(method)) {
Thread.onSpinWait();
if (!WHITE_BOX.isMethodCompiled(method)) {
throw new AssertionError("Method not compiled");
}
NMethod originalNMethod = NMethod.get(method, false);
@ -164,13 +103,9 @@ class DoWork {
WHITE_BOX.deoptimizeAll();
WHITE_BOX.fullGC();
WHITE_BOX.fullGC();
WHITE_BOX.lockCompilation();
System.out.printf("Relocated nmethod from 0x%016x to 0x%016x%n", originalNMethod.code_begin, relocatedNMethod.code_begin);
System.out.flush();
while (!shouldExit()) {
WHITE_BOX.fullGC();
}
}
public static long compiledMethod() {

View File

@ -21,10 +21,20 @@
* questions.
*/
#include <atomic>
#include <inttypes.h>
#include <jvmti.h>
#include <stdio.h>
#include <string.h>
#include "jvmti_common.hpp"
extern "C" {
// Track nmethod addresses for LOAD and UNLOAD events
static const void* first_load_addr = nullptr;
static const void* second_load_addr = nullptr;
static const void* first_unload_addr = nullptr;
static const void* second_unload_addr = nullptr;
// Keep track of test completion
static std::atomic<bool> should_exit{false};
/**
* Callback for COMPILED_METHOD_LOAD event.
@ -34,18 +44,27 @@ callbackCompiledMethodLoad(jvmtiEnv* jvmti, jmethodID method,
jint code_size, const void* code_addr,
jint map_length, const jvmtiAddrLocationMap* map,
const void* compile_info) {
char* name = nullptr;
char* sig = nullptr;
if (jvmti->GetMethodName(method, &name, &sig, nullptr) != JVMTI_ERROR_NONE) {
printf(" [Could not retrieve method name]\n");
fflush(stdout);
// Only track events for "compiledMethod"
char* name = get_method_name(jvmti, method);
if (strcmp(name, "compiledMethod") != 0) {
return;
}
printf("<COMPILED_METHOD_LOAD>: name: %s, code: 0x%016" PRIxPTR "\n",
name, (uintptr_t)code_addr);
fflush(stdout);
LOG("<COMPILED_METHOD_LOAD>: name: %s, code: 0x%016" PRIxPTR "\n", name, (uintptr_t)code_addr);
if (first_load_addr == nullptr) {
first_load_addr = code_addr;
} else if (second_load_addr == nullptr) {
second_load_addr = code_addr;
// Verify that the addresses are different
if (first_load_addr == second_load_addr) {
fatal("Load events for 'compiledMethod' are expected to use different addresses");
}
} else {
fatal("Received too many load events for 'compiledMethod'");
}
}
/**
@ -54,25 +73,50 @@ callbackCompiledMethodLoad(jvmtiEnv* jvmti, jmethodID method,
JNIEXPORT void JNICALL
callbackCompiledMethodUnload(jvmtiEnv* jvmti, jmethodID method,
const void* code_addr) {
char* name = nullptr;
char* sig = nullptr;
if (jvmti->GetMethodName(method, &name, &sig, nullptr) != JVMTI_ERROR_NONE) {
printf(" [Could not retrieve method name]\n");
fflush(stdout);
// Only track events for "compiledMethod"
char* name = get_method_name(jvmti, method);
if (strcmp(name, "compiledMethod") != 0) {
return;
}
printf("<COMPILED_METHOD_UNLOAD>: name: %s, code: 0x%016" PRIxPTR "\n",
name, (uintptr_t)code_addr);
fflush(stdout);
LOG("<COMPILED_METHOD_UNLOAD>: name: %s, code: 0x%016" PRIxPTR "\n", name, (uintptr_t)code_addr);
// Validate both loads have occurred
if (first_load_addr == nullptr || second_load_addr == nullptr) {
fatal("UNLOAD event for 'compiledMethod' occurred before both LOAD events");
}
if (first_unload_addr == nullptr) {
first_unload_addr = code_addr;
} else if (second_unload_addr == nullptr) {
second_unload_addr = code_addr;
// Verify that the addresses are different
if (first_unload_addr == second_unload_addr) {
fatal("Unload events for 'compiledMethod' are expected to use different addresses");
}
// LOAD and UNLOAD events should report the same two addresses, but the order of
// the UNLOADs is not guaranteed, since the GC may unload either nmethod first.
if ((first_load_addr == first_unload_addr && second_load_addr == second_unload_addr) ||
(first_load_addr == second_unload_addr && second_load_addr == first_unload_addr)) {
// Update should_exit to signal test completion
should_exit.store(true);
} else {
fatal("Address mismatch for 'compiledMethod' events");
}
} else {
fatal("Received too many unload events for 'compiledMethod'");
}
}
JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) {
jvmtiEnv* jvmti = nullptr;
jvmtiError error;
if (jvm->GetEnv((void **)&jvmti, JVMTI_VERSION_1_0) != JNI_OK) {
printf("Unable to access JVMTI!\n");
LOG("Unable to access JVMTI!\n");
return JNI_ERR;
}
@ -80,11 +124,8 @@ JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options, void *reserved)
jvmtiCapabilities caps;
memset(&caps, 0, sizeof(caps));
caps.can_generate_compiled_method_load_events = 1;
error = jvmti->AddCapabilities(&caps);
if (error != JVMTI_ERROR_NONE) {
printf("ERROR: Unable to add capabilities, error=%d\n", error);
return JNI_ERR;
}
jvmtiError error = jvmti->AddCapabilities(&caps);
check_jvmti_error(error, "Unable to add capabilities");
// Set event callbacks
jvmtiEventCallbacks eventCallbacks;
@ -92,23 +133,21 @@ JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options, void *reserved)
eventCallbacks.CompiledMethodLoad = callbackCompiledMethodLoad;
eventCallbacks.CompiledMethodUnload = callbackCompiledMethodUnload;
error = jvmti->SetEventCallbacks(&eventCallbacks, sizeof(eventCallbacks));
if (error != JVMTI_ERROR_NONE) {
printf("ERROR: Unable to set event callbacks, error=%d\n", error);
return JNI_ERR;
}
check_jvmti_error(error, "Unable to set event callbacks");
// Enable events
error = jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_COMPILED_METHOD_LOAD, nullptr);
if (error != JVMTI_ERROR_NONE) {
printf("ERROR: Unable to enable COMPILED_METHOD_LOAD event, error=%d\n", error);
return JNI_ERR;
}
check_jvmti_error(error, "Unable to enable COMPILED_METHOD_LOAD event");
error = jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_COMPILED_METHOD_UNLOAD, nullptr);
if (error != JVMTI_ERROR_NONE) {
printf("ERROR: Unable to enable COMPILED_METHOD_UNLOAD event, error=%d\n", error);
return JNI_ERR;
}
check_jvmti_error(error, "Unable to enable COMPILED_METHOD_UNLOAD event");
return JNI_OK;
}
JNIEXPORT jboolean JNICALL
Java_NMethodRelocationTest_shouldExit(JNIEnv *env, jclass cls) {
return should_exit.load();
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2007, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -28,6 +28,7 @@
* @summary converted from VM Testbase gc/gctests/MemoryEaterMT.
* VM Testbase keywords: [gc, stress, stressopt, nonconcurrent]
*
* @requires test.thread.factory != "Virtual"
* @library /vmTestbase
* /test/lib
* @run main/othervm -XX:-UseGCOverheadLimit gc.gctests.MemoryEaterMT.MemoryEaterMT

View File

@ -1,6 +1,6 @@
###########################################################################
#
# Copyright (c) 2009, 2025, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2009, 2026, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@ -561,8 +561,6 @@ java/net/MulticastSocket/Test.java 7145658,8308807
# jdk_nio
java/nio/channels/AsyncCloseAndInterrupt.java 8368290 macosx-26.0.1
java/nio/channels/DatagramChannel/AdaptorMulticasting.java 8308807,8144003 aix-ppc64,macosx-all
java/nio/channels/DatagramChannel/AfterDisconnect.java 8308807 aix-ppc64
java/nio/channels/DatagramChannel/ManySourcesAndTargets.java 8264385 macosx-aarch64

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -44,7 +44,6 @@ import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import jdk.test.lib.Platform;
import jdk.test.lib.Platform;
import static java.lang.System.err;
import static java.lang.System.out;
@ -103,16 +102,11 @@ public class GetXSpace {
private final long free;
private final long available;
Space(String name) {
Space(String name) throws IOException {
this.name = name;
long[] sizes = new long[4];
if (Platform.isWindows() && isCDDrive(name)) {
try {
getCDDriveSpace(name, sizes);
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException("can't get CDDrive sizes");
}
getCDDriveSpace(name, sizes);
} else {
if (getSpace(name, sizes))
System.err.println("WARNING: total space is estimated");
@ -170,7 +164,7 @@ public class GetXSpace {
return al;
}
private static void compare(Space s) {
private static void compare(Space s) throws IOException {
File f = new File(s.name());
long ts = f.getTotalSpace();
long fs = f.getFreeSpace();
@ -318,7 +312,7 @@ public class GetXSpace {
}
}
private static int testFile(Path dir) {
private static int testFile(Path dir) throws IOException {
String dirName = dir.toString();
out.format("--- Testing %s%n", dirName);
compare(new Space(dir.getRoot().toString()));
@ -333,10 +327,11 @@ public class GetXSpace {
return fail != 0 ? 1 : 0;
}
private static int testVolumes() {
private static int testVolumes() throws IOException {
out.println("--- Testing volumes");
// Find all of the partitions on the machine and verify that the sizes
// returned by File::getXSpace are equivalent to those from getSpace or getCDDriveSpace
// returned by File::getXSpace are equivalent to those from getSpace
// or getCDDriveSpace
ArrayList<String> l;
try {
l = paths();
@ -350,7 +345,18 @@ public class GetXSpace {
throw new RuntimeException("no partitions?");
for (var p : l) {
Space s = new Space(p);
Space s;
try {
s = new Space(p);
} catch (IOException x) {
// Avoid failing for transient file systems on Windows
if (Platform.isWindows()) {
File f = new File(p);
if (!f.exists())
continue;
}
throw new IOException("Failure for volume " + p, x);
}
compare(s);
compareZeroNonExist();
compareZeroExist();
@ -408,19 +414,19 @@ public class GetXSpace {
// size[2] free space: number of free bytes in the volume
// size[3] usable space: number of bytes available to the caller
//
private static native boolean getSpace0(String root, long[] space);
private static native boolean getSpace0(String root, long[] space)
throws IOException;
private static native boolean isCDDrive(String root);
private static boolean getSpace(String root, long[] space) {
private static boolean getSpace(String root, long[] space)
throws IOException {
try {
return getSpace0(root, space);
} catch (RuntimeException e) {
} catch (IOException e) {
File f = new File(root);
boolean exists = f.exists();
boolean readable = f.canRead();
System.err.printf("getSpace0 failed for %s (%s, %s)%n",
root, exists, readable);
root, f.exists(), f.canRead());
throw e;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -85,7 +85,7 @@ Java_GetXSpace_getSpace0
BOOL hres = pfnGetDiskSpaceInformation(path, &diskSpaceInfo);
(*env)->ReleaseStringChars(env, root, strchars);
if (FAILED(hres)) {
JNU_ThrowByNameWithLastError(env, "java/lang/RuntimeException",
JNU_ThrowByNameWithLastError(env, "java/io/IOException",
"GetDiskSpaceInformationW");
return totalSpaceIsEstimated;
}
@ -113,7 +113,7 @@ Java_GetXSpace_getSpace0
&totalNumberOfBytes, &totalNumberOfFreeBytes);
(*env)->ReleaseStringChars(env, root, strchars);
if (FAILED(hres)) {
JNU_ThrowByNameWithLastError(env, "java/lang/RuntimeException",
JNU_ThrowByNameWithLastError(env, "java/io/IOException",
"GetDiskFreeSpaceExW");
return totalSpaceIsEstimated;
}
@ -131,8 +131,7 @@ Java_GetXSpace_getSpace0
char* chars = (char*)malloc((len + 1)*sizeof(char));
if (chars == NULL) {
(*env)->ReleaseStringChars(env, root, strchars);
JNU_ThrowByNameWithLastError(env, "java/lang/RuntimeException",
"malloc");
JNU_ThrowOutOfMemoryError(env, "malloc");
return JNI_FALSE;
}
@ -146,7 +145,7 @@ Java_GetXSpace_getSpace0
int result = statfs(chars, &buf);
free(chars);
if (result < 0) {
JNU_ThrowByNameWithLastError(env, "java/lang/RuntimeException",
JNU_ThrowByNameWithLastError(env, "java/io/IOException",
strerror(errno));
return totalSpaceIsEstimated;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -62,13 +62,13 @@ import java.util.stream.Stream;
* @test
* @summary Tests security properties passed through java.security,
* java.security.properties or included from other properties files.
* @bug 8155246 8292297 8292177 8281658 8319332
* @bug 4303068 8155246 8292297 8292177 8281658 8319332
* @modules java.base/sun.net.www
* @library /test/lib
* @run main ConfigFileTest
* @run main ExtraFileAndIncludes
*/
public class ConfigFileTest {
public class ExtraFileAndIncludes {
static final String SEPARATOR_THIN = "----------------------------";
private static void printTestHeader(String testName) {
@ -91,7 +91,8 @@ public class ConfigFileTest {
} else {
// Executed by the test JVM.
try (FilesManager filesMgr = new FilesManager()) {
for (Method m : ConfigFileTest.class.getDeclaredMethods()) {
for (Method m :
ExtraFileAndIncludes.class.getDeclaredMethods()) {
if (m.getName().startsWith("test")) {
printTestHeader(m.getName());
Executor.run(m, filesMgr);
@ -120,7 +121,7 @@ public class ConfigFileTest {
static void testIncludeBasic(Executor ex, FilesManager filesMgr)
throws Exception {
PropsFile masterFile = filesMgr.newMasterFile();
ExtraPropsFile extraFile = filesMgr.newExtraFile();
ExtraPropsFile extraFile = filesMgr.newExtraFile(ExtraMode.FILE_URI);
PropsFile file0 = filesMgr.newFile("file0.properties");
PropsFile file1 = filesMgr.newFile("dir1/file1.properties");
PropsFile file2 = filesMgr.newFile("dir1/dir2/file2.properties");
@ -130,7 +131,7 @@ public class ConfigFileTest {
file2.addAbsoluteInclude(file1);
ex.setMasterFile(masterFile);
ex.setExtraFile(extraFile, Executor.ExtraMode.FILE_URI, false);
ex.setExtraFile(extraFile, false);
ex.assertSuccess();
}
@ -152,7 +153,7 @@ public class ConfigFileTest {
static void testIncludeWithOverrideAll(Executor ex, FilesManager filesMgr)
throws Exception {
PropsFile masterFile = filesMgr.newMasterFile();
ExtraPropsFile extraFile = filesMgr.newExtraFile();
ExtraPropsFile extraFile = filesMgr.newExtraFile(ExtraMode.HTTP_SERVED);
PropsFile file0 = filesMgr.newFile("file0.properties");
PropsFile file1 = filesMgr.newFile("dir1/file1.properties");
@ -160,40 +161,40 @@ public class ConfigFileTest {
extraFile.addAbsoluteInclude(file1);
ex.setMasterFile(masterFile);
ex.setExtraFile(extraFile, Executor.ExtraMode.HTTP_SERVED, true);
ex.setExtraFile(extraFile, true);
ex.assertSuccess();
}
static void extraPropertiesByHelper(Executor ex, FilesManager filesMgr,
Executor.ExtraMode mode) throws Exception {
ExtraPropsFile extraFile = filesMgr.newExtraFile();
ExtraMode mode) throws Exception {
ExtraPropsFile extraFile = filesMgr.newExtraFile(mode);
PropsFile file0 = filesMgr.newFile("file0.properties");
extraFile.addRelativeInclude(file0);
ex.setMasterFile(filesMgr.newMasterFile());
ex.setExtraFile(extraFile, mode, true);
ex.setExtraFile(extraFile, true);
ex.assertSuccess();
}
static void testExtraPropertiesByPathAbsolute(Executor ex,
FilesManager filesMgr) throws Exception {
extraPropertiesByHelper(ex, filesMgr, Executor.ExtraMode.PATH_ABS);
extraPropertiesByHelper(ex, filesMgr, ExtraMode.PATH_ABS);
}
static void testExtraPropertiesByPathRelative(Executor ex,
FilesManager filesMgr) throws Exception {
extraPropertiesByHelper(ex, filesMgr, Executor.ExtraMode.PATH_REL);
extraPropertiesByHelper(ex, filesMgr, ExtraMode.PATH_REL);
}
static void specialCharsIncludes(Executor ex, FilesManager filesMgr,
char specialChar, Executor.ExtraMode extraMode,
boolean useRelativeIncludes) throws Exception {
char specialChar, ExtraMode extraMode, boolean useRelativeIncludes)
throws Exception {
String suffix = specialChar + ".properties";
ExtraPropsFile extraFile;
PropsFile file0, file1;
try {
extraFile = filesMgr.newExtraFile("extra" + suffix);
extraFile = filesMgr.newExtraFile("extra" + suffix, extraMode);
file0 = filesMgr.newFile("file0" + suffix);
file1 = filesMgr.newFile("file1" + suffix);
} catch (InvalidPathException ipe) {
@ -210,20 +211,18 @@ public class ConfigFileTest {
extraFile.addAbsoluteInclude(file1);
ex.setMasterFile(filesMgr.newMasterFile());
ex.setExtraFile(extraFile, extraMode, false);
ex.setExtraFile(extraFile, false);
ex.assertSuccess();
}
static void testUnicodeIncludes1(Executor ex, FilesManager filesMgr)
throws Exception {
specialCharsIncludes(ex, filesMgr, '\u2022',
Executor.ExtraMode.PATH_ABS, true);
specialCharsIncludes(ex, filesMgr, '\u2022', ExtraMode.PATH_ABS, true);
}
static void testUnicodeIncludes2(Executor ex, FilesManager filesMgr)
throws Exception {
specialCharsIncludes(ex, filesMgr, '\u2022',
Executor.ExtraMode.FILE_URI, true);
specialCharsIncludes(ex, filesMgr, '\u2022', ExtraMode.FILE_URI, true);
}
static void testUnicodeIncludes3(Executor ex, FilesManager filesMgr)
@ -232,7 +231,7 @@ public class ConfigFileTest {
// file:/tmp/extra.properties are supported for the extra file.
// However, relative includes are not allowed in these cases.
specialCharsIncludes(ex, filesMgr, '\u2022',
Executor.ExtraMode.RAW_FILE_URI1, false);
ExtraMode.RAW_FILE_URI1, false);
}
static void testUnicodeIncludes4(Executor ex, FilesManager filesMgr)
@ -241,19 +240,17 @@ public class ConfigFileTest {
// file:///tmp/extra.properties are supported for the extra file.
// However, relative includes are not allowed in these cases.
specialCharsIncludes(ex, filesMgr, '\u2022',
Executor.ExtraMode.RAW_FILE_URI2, false);
ExtraMode.RAW_FILE_URI2, false);
}
static void testSpaceIncludes1(Executor ex, FilesManager filesMgr)
throws Exception {
specialCharsIncludes(ex, filesMgr, ' ',
Executor.ExtraMode.PATH_ABS, true);
specialCharsIncludes(ex, filesMgr, ' ', ExtraMode.PATH_ABS, true);
}
static void testSpaceIncludes2(Executor ex, FilesManager filesMgr)
throws Exception {
specialCharsIncludes(ex, filesMgr, ' ',
Executor.ExtraMode.FILE_URI, true);
specialCharsIncludes(ex, filesMgr, ' ', ExtraMode.FILE_URI, true);
}
static void testSpaceIncludes3(Executor ex, FilesManager filesMgr)
@ -261,8 +258,7 @@ public class ConfigFileTest {
// Backward compatibility check. Malformed URLs such as
// file:/tmp/extra .properties are supported for the extra file.
// However, relative includes are not allowed in these cases.
specialCharsIncludes(ex, filesMgr, ' ',
Executor.ExtraMode.RAW_FILE_URI1, false);
specialCharsIncludes(ex, filesMgr, ' ', ExtraMode.RAW_FILE_URI1, false);
}
static void testSpaceIncludes4(Executor ex, FilesManager filesMgr)
@ -270,8 +266,7 @@ public class ConfigFileTest {
// Backward compatibility check. Malformed URLs such as
// file:///tmp/extra .properties are supported for the extra file.
// However, relative includes are not allowed in these cases.
specialCharsIncludes(ex, filesMgr, ' ',
Executor.ExtraMode.RAW_FILE_URI2, false);
specialCharsIncludes(ex, filesMgr, ' ', ExtraMode.RAW_FILE_URI2, false);
}
static void notOverrideOnFailureHelper(Executor ex, FilesManager filesMgr,
@ -370,13 +365,13 @@ public class ConfigFileTest {
static void testCannotResolveRelativeFromHTTPServed(Executor ex,
FilesManager filesMgr) throws Exception {
ExtraPropsFile extraFile = filesMgr.newExtraFile();
ExtraPropsFile extraFile = filesMgr.newExtraFile(ExtraMode.HTTP_SERVED);
PropsFile file0 = filesMgr.newFile("file0.properties");
extraFile.addRelativeInclude(file0);
ex.setMasterFile(filesMgr.newMasterFile());
ex.setExtraFile(extraFile, Executor.ExtraMode.HTTP_SERVED, true);
ex.setExtraFile(extraFile, true);
ex.assertError("InternalError: Cannot resolve '" + file0.fileName +
"' relative path when included from a non-regular " +
"properties file (e.g. HTTP served file)");
@ -394,14 +389,15 @@ public class ConfigFileTest {
masterFile.addRelativeInclude(file0);
ex.setMasterFile(masterFile);
ex.assertError(
"InternalError: Cyclic include of '" + masterFile.path + "'");
ex.assertError("Cyclic include");
ex.getOutputAnalyzer().stderrShouldMatch("\\QInternalError: Cyclic " +
"include of '\\E[^']+\\Q" + masterFile.fileName + "'\\E");
}
static void testCannotIncludeURL(Executor ex, FilesManager filesMgr)
throws Exception {
PropsFile masterFile = filesMgr.newMasterFile();
ExtraPropsFile extraFile = filesMgr.newExtraFile();
ExtraPropsFile extraFile = filesMgr.newExtraFile(ExtraMode.HTTP_SERVED);
masterFile.addRawProperty("include", extraFile.url.toString());
@ -432,8 +428,7 @@ public class ConfigFileTest {
// Launch a JDK without a master java.security file present, but with an
// extra file passed. Since the "security.overridePropertiesFile=true"
// security property is missing, it should fail anyway.
ex.setExtraFile(
filesMgr.newExtraFile(), Executor.ExtraMode.FILE_URI, true);
ex.setExtraFile(filesMgr.newExtraFile(ExtraMode.FILE_URI), true);
ex.assertError("InternalError: Error loading java.security file");
}
}
@ -455,17 +450,24 @@ sealed class PropsFile permits ExtraPropsFile {
static Include of(PropsFile propsFile, String value) {
return new Include(propsFile, value);
}
void assertProcessed(OutputAnalyzer oa) {
oa.shouldContain("processing include: '" + value + "'");
oa.shouldContain("finished processing " + propsFile.displayPath);
}
}
protected final List<Include> includes = new ArrayList<>();
protected final PrintWriter writer;
protected boolean includedFromExtra = false;
protected Path displayPath;
final String fileName;
final Path path;
PropsFile(String fileName, Path path) throws IOException {
this.fileName = fileName;
this.path = path;
this.displayPath = path;
this.writer = new PrintWriter(Files.newOutputStream(path,
StandardOpenOption.CREATE, StandardOpenOption.APPEND), true);
}
@ -513,8 +515,9 @@ sealed class PropsFile permits ExtraPropsFile {
}
void addRelativeInclude(PropsFile propsFile) {
addIncludeDefinition(Include.of(propsFile,
path.getParent().relativize(propsFile.path).toString()));
Path rel = path.getParent().relativize(propsFile.path);
addIncludeDefinition(Include.of(propsFile, rel.toString()));
propsFile.displayPath = displayPath.getParent().resolve(rel);
}
void assertApplied(OutputAnalyzer oa) {
@ -522,8 +525,7 @@ sealed class PropsFile permits ExtraPropsFile {
FilesManager.APPLIED_PROP_VALUE);
for (Include include : includes) {
include.propsFile.assertApplied(oa);
oa.shouldContain("processing include: '" + include.value + "'");
oa.shouldContain("finished processing " + include.propsFile.path);
include.assertProcessed(oa);
}
}
@ -534,8 +536,7 @@ sealed class PropsFile permits ExtraPropsFile {
if (!include.propsFile.includedFromExtra) {
include.propsFile.assertWasOverwritten(oa);
}
oa.shouldContain("processing include: '" + include.value + "'");
oa.shouldContain("finished processing " + include.propsFile.path);
include.assertProcessed(oa);
}
}
@ -556,13 +557,24 @@ sealed class PropsFile permits ExtraPropsFile {
}
}
enum ExtraMode {
HTTP_SERVED, FILE_URI, RAW_FILE_URI1, RAW_FILE_URI2, PATH_ABS, PATH_REL
}
final class ExtraPropsFile extends PropsFile {
private static final Path CWD = Path.of(".").toAbsolutePath();
private final Map<String, String> systemProps = new LinkedHashMap<>();
private final ExtraMode mode;
final URI url;
ExtraPropsFile(String fileName, URI url, Path path) throws IOException {
ExtraPropsFile(String fileName, URI url, Path path, ExtraMode mode)
throws IOException {
super(fileName, path);
this.url = url;
this.mode = mode;
if (mode == ExtraMode.PATH_REL) {
this.displayPath = CWD.relativize(path);
}
}
@Override
@ -578,14 +590,25 @@ final class ExtraPropsFile extends PropsFile {
super.addIncludeDefinition(include);
}
String getSysPropValue() {
return switch (mode) {
case HTTP_SERVED -> url.toString();
case FILE_URI -> path.toUri().toString();
case RAW_FILE_URI1 -> "file:" + path;
case RAW_FILE_URI2 ->
"file://" + (path.startsWith("/") ? "" : "/") + path;
case PATH_ABS, PATH_REL -> displayPath.toString();
};
}
Map<String, String> getSystemProperties() {
return Collections.unmodifiableMap(systemProps);
}
}
final class FilesManager implements Closeable {
private static final Path ROOT_DIR =
Path.of(ConfigFileTest.class.getSimpleName()).toAbsolutePath();
private static final Path ROOT_DIR = Path.of(
ExtraFileAndIncludes.class.getSimpleName()).toAbsolutePath();
private static final Path PROPS_DIR = ROOT_DIR.resolve("properties");
private static final Path JDK_DIR = ROOT_DIR.resolve("jdk");
private static final Path MASTER_FILE =
@ -684,11 +707,11 @@ final class FilesManager implements Closeable {
propsFile.addComment("Property to determine if this properties file " +
"was parsed and not overwritten:");
propsFile.addRawProperty(fileName, APPLIED_PROP_VALUE);
propsFile.addComment(ConfigFileTest.SEPARATOR_THIN);
propsFile.addComment(ExtraFileAndIncludes.SEPARATOR_THIN);
propsFile.addComment("Property to be overwritten by every properties " +
"file (master, extra or included):");
propsFile.addRawProperty(LAST_FILE_PROP_NAME, fileName);
propsFile.addComment(ConfigFileTest.SEPARATOR_THIN);
propsFile.addComment(ExtraFileAndIncludes.SEPARATOR_THIN);
createdFiles.add(propsFile);
return propsFile;
}
@ -702,16 +725,17 @@ final class FilesManager implements Closeable {
return newFile(MASTER_FILE, PropsFile::new);
}
ExtraPropsFile newExtraFile() throws IOException {
return newExtraFile("extra.properties");
ExtraPropsFile newExtraFile(ExtraMode mode) throws IOException {
return newExtraFile("extra.properties", mode);
}
ExtraPropsFile newExtraFile(String extraFileName) throws IOException {
ExtraPropsFile newExtraFile(String extraFileName, ExtraMode mode)
throws IOException {
return (ExtraPropsFile) newFile(PROPS_DIR.resolve(extraFileName),
(fileName, path) -> {
URI uri = serverUri.resolve(ParseUtil.encodePath(
ROOT_DIR.relativize(path).toString()));
return new ExtraPropsFile(fileName, uri, path);
return new ExtraPropsFile(fileName, uri, path, mode);
});
}
@ -719,7 +743,7 @@ final class FilesManager implements Closeable {
for (PropsFile propsFile : createdFiles) {
System.err.println();
System.err.println(propsFile.path.toString());
System.err.println(ConfigFileTest.SEPARATOR_THIN.repeat(3));
System.err.println(ExtraFileAndIncludes.SEPARATOR_THIN.repeat(3));
try (Stream<String> lines = Files.lines(propsFile.path)) {
long lineNumber = 1L;
Iterator<String> it = lines.iterator();
@ -757,9 +781,6 @@ final class FilesManager implements Closeable {
}
final class Executor {
enum ExtraMode {
HTTP_SERVED, FILE_URI, RAW_FILE_URI1, RAW_FILE_URI2, PATH_ABS, PATH_REL
}
static final String RUNNER_ARG = "runner";
static final String INITIAL_PROP_LOG_MSG = "Initial security property: ";
private static final String OVERRIDING_LOG_MSG =
@ -769,7 +790,6 @@ final class Executor {
INITIAL_PROP_LOG_MSG + "postInitTest=shouldNotRecord",
INITIAL_PROP_LOG_MSG + "include=",
};
private static final Path CWD = Path.of(".").toAbsolutePath();
private static final String JAVA_SEC_PROPS = "java.security.properties";
private static final String CLASS_PATH = Objects.requireNonNull(
System.getProperty("test.classes"), "unspecified test.classes");
@ -812,20 +832,10 @@ final class Executor {
this.masterPropsFile = masterPropsFile;
}
void setExtraFile(ExtraPropsFile extraPropsFile, ExtraMode mode,
boolean overrideAll) {
void setExtraFile(ExtraPropsFile extraPropsFile, boolean overrideAll) {
this.extraPropsFile = extraPropsFile;
expectedOverrideAll = overrideAll;
setRawExtraFile(switch (mode) {
case HTTP_SERVED -> extraPropsFile.url.toString();
case FILE_URI -> extraPropsFile.path.toUri().toString();
case RAW_FILE_URI1 -> "file:" + extraPropsFile.path;
case RAW_FILE_URI2 -> "file://" +
(extraPropsFile.path.startsWith("/") ? "" : "/") +
extraPropsFile.path;
case PATH_ABS -> extraPropsFile.path.toString();
case PATH_REL -> CWD.relativize(extraPropsFile.path).toString();
}, overrideAll);
setRawExtraFile(extraPropsFile.getSysPropValue(), overrideAll);
}
void setIgnoredExtraFile(String extraPropsFile, boolean overrideAll) {
@ -841,7 +851,7 @@ final class Executor {
List<String> command = new ArrayList<>(jvmArgs);
Collections.addAll(command, Utils.getTestJavaOpts());
addSystemPropertiesAsJvmArgs(command);
command.add(ConfigFileTest.class.getSimpleName());
command.add(ExtraFileAndIncludes.class.getSimpleName());
command.add(RUNNER_ARG);
oa = ProcessTools.executeProcess(new ProcessBuilder(command));
oa.shouldHaveExitValue(successExpected ? 0 : 1);

View File

@ -0,0 +1,83 @@
/*
* Copyright (c) 2026, Red Hat, Inc.
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import jdk.test.lib.process.ProcessTools;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Path;
/*
* @test
* @summary Ensures the java executable is able to load extra security
* properties files from anonymous files and pipes.
* @bug 8352728
* @requires os.family == "linux"
* @modules java.base/java.io:+open
* @library /test/lib
* @run main LinuxAnonymousFiles
*/
public class LinuxAnonymousFiles {
private static final String TEST_PROP = "property.name=PROPERTY_VALUE";
private static final class AnonymousFile implements AutoCloseable {
public final Path fdPath;
private final FileInputStream fis;
private AnonymousFile(CharSequence content) throws Exception {
Path tmp = Files.createTempFile("anonymous-file-", "");
Files.writeString(tmp, content + System.lineSeparator());
fis = new FileInputStream(tmp.toFile());
Files.delete(tmp);
// Now the file is regular but anonymous, and will be unlinked
// when we close the last file descriptor referring to it. The
// fis instance ensures we keep it alive until close() is invoked.
Field field = FileDescriptor.class.getDeclaredField("fd");
field.setAccessible(true);
int fd = field.getInt(fis.getFD());
fdPath = Path.of("/proc/self").toRealPath().resolve("fd/" + fd);
}
@Override
public void close() throws IOException {
fis.close();
}
}
public static void main(String[] args) throws Exception {
Path java = Path.of(System.getProperty("test.jdk"), "bin", "java");
try (AnonymousFile af = new AnonymousFile("include /dev/stdin")) {
ProcessTools.executeProcess(new ProcessBuilder(java.toString(),
"-Djava.security.debug=properties",
"-Djava.security.properties=" + af.fdPath,
"-XshowSettings:security:properties", "-version"),
TEST_PROP).shouldHaveExitValue(0).shouldContain(TEST_PROP);
}
System.out.println("TEST PASS - OK");
}
}

View File

@ -1 +0,0 @@
policy.url.2=file:${test.src}/SecurityPropFile.policy

View File

@ -1,42 +0,0 @@
/*
* 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
* 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 4303068
* @summary be allowed to specify the security properties file
* as a -D system property
*
* @run main/othervm -Djava.security.properties=${test.src}/SecurityPropFile.file -Djava.security.debug=properties SecurityPropFile
*/
public class SecurityPropFile {
public static void main(String[] args) {
System.out.println(java.security.Security.getProperty
("policy.provider"));
System.out.println(java.security.Security.getProperty
("policy.url.1"));
System.out.println(java.security.Security.getProperty
("policy.url.2"));
}
}

View File

@ -0,0 +1,84 @@
/*
* Copyright (c) 2026, Red Hat, Inc.
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import jdk.test.lib.process.ProcessTools;
import jdk.test.lib.util.FileUtils;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.AclEntry;
import java.nio.file.attribute.AclEntryType;
import java.nio.file.attribute.AclFileAttributeView;
import java.util.List;
/*
* @test
* @summary Ensures java.security is loadable in Windows, even when the user
* does not have permissions on one of the parent directories.
* @bug 8352728
* @requires os.family == "windows"
* @library /test/lib
* @run main WindowsParentDirPermissions
*/
public class WindowsParentDirPermissions {
private static AutoCloseable restrictedAcl(Path path) throws IOException {
AclFileAttributeView view =
Files.getFileAttributeView(path, AclFileAttributeView.class);
List<AclEntry> originalAcl = List.copyOf(view.getAcl());
view.setAcl(List.of(AclEntry.newBuilder().setType(AclEntryType.DENY)
.setPrincipal(Files.getOwner(path)).build()));
return () -> view.setAcl(originalAcl);
}
public static void main(String[] args) throws Exception {
Path temp = Files.createTempDirectory("JDK-8352728-tmp-");
try (AutoCloseable a1 = () -> FileUtils.deleteFileTreeUnchecked(temp)) {
// Copy the jdk to a different directory
Path originalJdk = Path.of(System.getProperty("test.jdk"));
Path jdk = temp.resolve("jdk-parent-dir", "jdk");
Files.createDirectories(jdk);
FileUtils.copyDirectory(originalJdk, jdk);
// Remove current user permissions from jdk-parent-dir
try (AutoCloseable a2 = restrictedAcl(jdk.getParent())) {
// Make sure the permissions are affecting the current user
try {
jdk.toRealPath();
throw new jtreg.SkippedException("Must run non-elevated!");
} catch (IOException expected) { }
// Execute the copied jdk, ensuring java.security.Security is
// loaded (i.e. use -XshowSettings:security:properties)
ProcessTools.executeProcess(new ProcessBuilder(
List.of(jdk.resolve("bin", "java.exe").toString(),
"-Djava.security.debug=properties",
"-XshowSettings:security:properties",
"-version"))).shouldHaveExitValue(0);
}
}
System.out.println("TEST PASS - OK");
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -59,8 +59,11 @@
*/
package tck.java.time;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.fail;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.time.DateTimeException;
import java.time.temporal.TemporalAccessor;
@ -68,8 +71,8 @@ import java.time.temporal.TemporalField;
import java.time.temporal.TemporalQuery;
import java.util.List;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import test.java.time.temporal.MockFieldNoValue;
@ -99,183 +102,137 @@ public abstract class AbstractDateTimeTest extends AbstractTCKTest {
//-----------------------------------------------------------------------
// isSupported(TemporalField)
//-----------------------------------------------------------------------
@Test()
public void basicTest_isSupported_TemporalField_supported() {
for (TemporalAccessor sample : samples()) {
for (TemporalField field : validFields()) {
assertEquals(true, sample.isSupported(field), "Failed on " + sample + " " + field);
}
@ParameterizedTest
@MethodSource("samples")
public void basicTest_isSupported_TemporalField_supported(TemporalAccessor sample) {
for (TemporalField field : validFields()) {
assertTrue(sample.isSupported(field), "Failed on " + sample + " " + field);
}
}
@Test()
public void basicTest_isSupported_TemporalField_unsupported() {
for (TemporalAccessor sample : samples()) {
for (TemporalField field : invalidFields()) {
assertEquals(false, sample.isSupported(field), "Failed on " + sample + " " + field);
}
@ParameterizedTest
@MethodSource("samples")
public void basicTest_isSupported_TemporalField_unsupported(TemporalAccessor sample) {
for (TemporalField field : invalidFields()) {
assertFalse(sample.isSupported(field), "Failed on " + sample + " " + field);
}
}
@Test()
public void basicTest_isSupported_TemporalField_null() {
for (TemporalAccessor sample : samples()) {
assertEquals(false, sample.isSupported(null), "Failed on " + sample);
}
@ParameterizedTest
@MethodSource("samples")
public void basicTest_isSupported_TemporalField_null(TemporalAccessor sample) {
assertFalse(sample.isSupported(null), "Failed on " + sample);
}
//-----------------------------------------------------------------------
// range(TemporalField)
//-----------------------------------------------------------------------
@Test()
public void basicTest_range_TemporalField_supported() {
for (TemporalAccessor sample : samples()) {
for (TemporalField field : validFields()) {
sample.range(field); // no exception
}
@ParameterizedTest
@MethodSource("samples")
public void basicTest_range_TemporalField_supported(TemporalAccessor sample) {
for (TemporalField field : validFields()) {
assertDoesNotThrow(() -> sample.range(field));
}
}
@Test()
public void basicTest_range_TemporalField_unsupported() {
for (TemporalAccessor sample : samples()) {
for (TemporalField field : invalidFields()) {
try {
sample.range(field);
fail("Failed on " + sample + " " + field);
} catch (DateTimeException ex) {
// expected
}
}
@ParameterizedTest
@MethodSource("samples")
public void basicTest_range_TemporalField_unsupported(TemporalAccessor sample) {
for (TemporalField field : invalidFields()) {
assertThrows(DateTimeException.class,
() -> sample.range(field), "Failed on " + sample + " " + field);
}
}
@Test()
public void basicTest_range_TemporalField_null() {
for (TemporalAccessor sample : samples()) {
try {
sample.range(null);
fail("Failed on " + sample);
} catch (NullPointerException ex) {
// expected
}
}
@ParameterizedTest
@MethodSource("samples")
public void basicTest_range_TemporalField_null(TemporalAccessor sample) {
assertThrows(NullPointerException.class,
() -> sample.range(null), "Failed on " + sample);
}
//-----------------------------------------------------------------------
// get(TemporalField)
//-----------------------------------------------------------------------
@Test()
public void basicTest_get_TemporalField_supported() {
for (TemporalAccessor sample : samples()) {
for (TemporalField field : validFields()) {
if (sample.range(field).isIntValue()) {
sample.get(field); // no exception
} else {
try {
sample.get(field);
fail("Failed on " + sample + " " + field);
} catch (DateTimeException ex) {
// expected
}
}
@ParameterizedTest
@MethodSource("samples")
public void basicTest_get_TemporalField_supported(TemporalAccessor sample) {
for (TemporalField field : validFields()) {
if (sample.range(field).isIntValue()) {
assertDoesNotThrow(() -> sample.get(field));
} else {
assertThrows(DateTimeException.class,
() -> sample.get(field), "Failed on " + sample + " " + field);
}
}
}
@Test()
public void basicTest_get_TemporalField_unsupported() {
for (TemporalAccessor sample : samples()) {
for (TemporalField field : invalidFields()) {
try {
sample.get(field);
fail("Failed on " + sample + " " + field);
} catch (DateTimeException ex) {
// expected
}
}
@ParameterizedTest
@MethodSource("samples")
public void basicTest_get_TemporalField_unsupported(TemporalAccessor sample) {
for (TemporalField field : invalidFields()) {
assertThrows(DateTimeException.class,
() -> sample.get(field), "Failed on " + sample + " " + field);
}
}
@Test
public void test_get_TemporalField_invalidField() {
Assertions.assertThrows(DateTimeException.class, () -> {
for (TemporalAccessor sample : samples()) {
sample.get(MockFieldNoValue.INSTANCE);
}
});
@ParameterizedTest
@MethodSource("samples")
public void test_get_TemporalField_invalidField(TemporalAccessor sample) {
assertThrows(DateTimeException.class,
() -> sample.get(MockFieldNoValue.INSTANCE));
}
@Test()
public void basicTest_get_TemporalField_null() {
for (TemporalAccessor sample : samples()) {
try {
sample.get(null);
fail("Failed on " + sample);
} catch (NullPointerException ex) {
// expected
}
}
@ParameterizedTest
@MethodSource("samples")
public void basicTest_get_TemporalField_null(TemporalAccessor sample) {
assertThrows(NullPointerException.class,
() -> sample.get(null), "Failed on " + sample);
}
//-----------------------------------------------------------------------
// getLong(TemporalField)
//-----------------------------------------------------------------------
@Test()
public void basicTest_getLong_TemporalField_supported() {
for (TemporalAccessor sample : samples()) {
for (TemporalField field : validFields()) {
sample.getLong(field); // no exception
}
@ParameterizedTest
@MethodSource("samples")
public void basicTest_getLong_TemporalField_supported(TemporalAccessor sample) {
for (TemporalField field : validFields()) {
sample.getLong(field);
}
}
@Test()
public void basicTest_getLong_TemporalField_unsupported() {
for (TemporalAccessor sample : samples()) {
for (TemporalField field : invalidFields()) {
try {
sample.getLong(field);
fail("Failed on " + sample + " " + field);
} catch (DateTimeException ex) {
// expected
}
}
@ParameterizedTest
@MethodSource("samples")
public void basicTest_getLong_TemporalField_unsupported(TemporalAccessor sample) {
for (TemporalField field : invalidFields()) {
assertThrows(DateTimeException.class,
() -> sample.getLong(field), "Failed on " + sample + " " + field);
}
}
@Test
public void test_getLong_TemporalField_invalidField() {
Assertions.assertThrows(DateTimeException.class, () -> {
for (TemporalAccessor sample : samples()) {
sample.getLong(MockFieldNoValue.INSTANCE);
}
});
@ParameterizedTest
@MethodSource("samples")
public void test_getLong_TemporalField_invalidField(TemporalAccessor sample) {
assertThrows(DateTimeException.class,
() -> sample.getLong(MockFieldNoValue.INSTANCE));
}
@Test()
public void basicTest_getLong_TemporalField_null() {
for (TemporalAccessor sample : samples()) {
try {
sample.getLong(null);
fail("Failed on " + sample);
} catch (NullPointerException ex) {
// expected
}
}
@ParameterizedTest
@MethodSource("samples")
public void basicTest_getLong_TemporalField_null(TemporalAccessor sample) {
assertThrows(NullPointerException.class,
() -> sample.getLong(null), "Failed on " + sample);
}
//-----------------------------------------------------------------------
@Test
public void basicTest_query() {
for (TemporalAccessor sample : samples()) {
assertEquals("foo", sample.query(new TemporalQuery<String>() {
@Override
public String queryFrom(TemporalAccessor temporal) {
return "foo";
}
}));
}
@ParameterizedTest
@MethodSource("samples")
public void basicTest_query(TemporalAccessor sample) {
assertEquals("foo", sample.query(new TemporalQuery<String>() {
@Override
public String queryFrom(TemporalAccessor temporal) {
return "foo";
}
}));
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -139,7 +139,8 @@ public class TCKInstant extends AbstractDateTimeTest {
//-----------------------------------------------------------------------
@Override
protected List<TemporalAccessor> samples() {
TemporalAccessor[] array = {TEST_12345_123456789, Instant.MIN, Instant.MAX, Instant.EPOCH};
TemporalAccessor[] array = {Instant.ofEpochSecond(12345, 123456789),
Instant.MIN, Instant.MAX, Instant.EPOCH};
return Arrays.asList(array);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -170,7 +170,7 @@ public class TCKLocalDate extends AbstractDateTimeTest {
//-----------------------------------------------------------------------
@Override
protected List<TemporalAccessor> samples() {
TemporalAccessor[] array = {TEST_2007_07_15, LocalDate.MAX, LocalDate.MIN, };
TemporalAccessor[] array = {LocalDate.of(2007, 7, 15), LocalDate.MAX, LocalDate.MIN, };
return Arrays.asList(array);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -161,7 +161,8 @@ public class TCKLocalTime extends AbstractDateTimeTest {
//-----------------------------------------------------------------------
@Override
protected List<TemporalAccessor> samples() {
TemporalAccessor[] array = {TEST_12_30_40_987654321, LocalTime.MIN, LocalTime.MAX, LocalTime.MIDNIGHT, LocalTime.NOON};
TemporalAccessor[] array = {LocalTime.of(12, 30, 40, 987654321),
LocalTime.MIN, LocalTime.MAX, LocalTime.MIDNIGHT, LocalTime.NOON};
return Arrays.asList(array);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -118,7 +118,7 @@ public class TCKMonthDay extends AbstractDateTimeTest {
//-----------------------------------------------------------------------
@Override
protected List<TemporalAccessor> samples() {
TemporalAccessor[] array = {TEST_07_15, };
TemporalAccessor[] array = {MonthDay.of(7, 15), };
return Arrays.asList(array);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -167,7 +167,8 @@ public class TCKOffsetDateTime extends AbstractDateTimeTest {
//-----------------------------------------------------------------------
@Override
protected List<TemporalAccessor> samples() {
TemporalAccessor[] array = {TEST_2008_6_30_11_30_59_000000500, OffsetDateTime.MIN, OffsetDateTime.MAX};
TemporalAccessor[] array = {OffsetDateTime.of(2008, 6, 30, 11, 30, 59, 500, OFFSET_PONE),
OffsetDateTime.MIN, OffsetDateTime.MAX};
return Arrays.asList(array);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -149,7 +149,8 @@ public class TCKOffsetTime extends AbstractDateTimeTest {
//-----------------------------------------------------------------------
@Override
protected List<TemporalAccessor> samples() {
TemporalAccessor[] array = {TEST_11_30_59_500_PONE, OffsetTime.MIN, OffsetTime.MAX};
TemporalAccessor[] array = {OffsetTime.of(11, 30, 59, 500, OFFSET_PONE),
OffsetTime.MIN, OffsetTime.MAX};
return Arrays.asList(array);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -134,7 +134,7 @@ public class TCKYearMonth extends AbstractDateTimeTest {
//-----------------------------------------------------------------------
@Override
protected List<TemporalAccessor> samples() {
TemporalAccessor[] array = {TEST_2008_06, };
TemporalAccessor[] array = {YearMonth.of(2008, 6), };
return Arrays.asList(array);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -176,7 +176,7 @@ public class TCKZonedDateTime extends AbstractDateTimeTest {
//-----------------------------------------------------------------------
@Override
protected List<TemporalAccessor> samples() {
TemporalAccessor[] array = {TEST_DATE_TIME, };
TemporalAccessor[] array = {ZonedDateTime.of(LocalDateTime.of(2008, 6, 30, 11, 30, 59, 500), ZONE_0100), };
return Arrays.asList(array);
}

View File

@ -1,108 +0,0 @@
/*
* Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 6657138
* @summary Verifies that buttons and labels don't share their ui's across appContexts
* @author Alexander Potochkin
* @modules java.desktop/sun.awt
*/
import sun.awt.SunToolkit;
import javax.swing.*;
import javax.swing.plaf.ButtonUI;
import javax.swing.plaf.ComponentUI;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class bug6657138 implements Runnable {
private static Map<JComponent, Map<String, ComponentUI>> componentMap =
Collections.synchronizedMap(
new HashMap<JComponent, Map<String, ComponentUI>>());
public void run() {
SunToolkit.createNewAppContext();
try {
testUIMap();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private static void testUIMap() throws Exception {
UIManager.LookAndFeelInfo[] lafs = UIManager.getInstalledLookAndFeels();
Set<JComponent> components = componentMap.keySet();
for (JComponent c : components) {
Map<String, ComponentUI> uiMap = componentMap.get(c);
for (UIManager.LookAndFeelInfo laf : lafs) {
if ("Nimbus".equals(laf.getName())) {
// for some unclear reasons
// Nimbus ui delegate for a button is null
// when this method is called from the new AppContext
continue;
}
String className = laf.getClassName();
try {
UIManager.setLookAndFeel(className);
} catch (final UnsupportedLookAndFeelException ignored) {
continue;
}
ComponentUI ui = UIManager.getUI(c);
if (ui == null) {
throw new RuntimeException("UI is null for " + c);
}
if (ui == uiMap.get(laf.getName())) {
throw new RuntimeException(
"Two AppContexts share the same UI delegate! \n" +
c + "\n" + ui);
}
uiMap.put(laf.getName(), ui);
}
}
}
public static void main(String[] args) throws Exception {
componentMap.put(new JButton("JButton"),
new HashMap<String, ComponentUI>());
componentMap.put(new JToggleButton("JToggleButton"),
new HashMap<String, ComponentUI>());
componentMap.put(new JRadioButton("JRadioButton"),
new HashMap<String, ComponentUI>());
componentMap.put(new JCheckBox("JCheckBox"),
new HashMap<String, ComponentUI>());
componentMap.put(new JCheckBox("JLabel"),
new HashMap<String, ComponentUI>());
testUIMap();
ThreadGroup group = new ThreadGroup("6657138");
Thread thread = new Thread(group, new bug6657138());
thread.start();
thread.join();
}
}

View File

@ -0,0 +1,167 @@
/*
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.jfr.event.tracing;
import java.nio.file.Path;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import jdk.jfr.Recording;
import jdk.jfr.consumer.RecordedEvent;
import jdk.jfr.consumer.RecordedMethod;
import jdk.jfr.consumer.RecordingFile;
import jdk.test.lib.jfr.Events;
/**
* @test
* @summary Tests that constructors are instrumented correctly.
* @requires vm.flagless
* @requires vm.hasJFR
* @library /test/lib
* @run main/othervm -Xlog:jfr+methodtrace=debug
* jdk.jfr.event.tracing.TestConstructors
**/
public class TestConstructors {
static private void methodThatThrows() {
throw new RuntimeException();
}
public static class Cat {
Cat() {
new String();
methodThatThrows();
super();
methodThatThrows();
}
}
public static class Dog {
Dog() {
super();
methodThatThrows();
}
}
public static class Tiger {
Tiger() {
methodThatThrows();
super();
}
}
public static class Zebra {
Zebra(boolean shouldThrow) {
this(shouldThrow ? 1 : 0);
}
Zebra(int shouldThrow) {
if (shouldThrow == 1) {
throw new RuntimeException();
}
}
}
public static class Snake {
Snake() {
try {
throw new RuntimeException();
} catch (Exception e) {
// Ignore
}
super();
}
}
public static void main(String... args) throws Exception {
try (Recording r = new Recording()) {
r.enable("jdk.MethodTrace").with("filter", Dog.class.getName() + ";" + Cat.class.getName() + ";" + Tiger.class.getName() + ";" + Zebra.class.getName() + ";" + Snake.class.getName());
r.start();
try {
new Cat();
} catch (Exception e) {
// ignore
}
try {
new Dog();
} catch (Exception e) {
// ignore
}
try {
new Tiger();
} catch (Exception e) {
// ignore
}
try {
new Zebra(true);
} catch (Exception e) {
// ignore
}
try {
new Zebra(false);
} catch (Exception e) {
// ignore
}
try {
new Snake();
} catch (Exception e) {
// ignore
}
r.stop();
List<RecordedEvent> events = Events.fromRecording(r);
var methods = buildMethodMap(events);
if (methods.size() != 5) {
throw new Exception("Expected 5 different methods");
}
assertMethodCount(methods, "Cat", 1);
assertMethodCount(methods, "Dog", 1);
assertMethodCount(methods, "Snake", 1);
assertMethodCount(methods, "Tiger", 1);
assertMethodCount(methods, "Zebra", 3);
}
}
private static void assertMethodCount(Map<String, Long> methods, String className, int expectedCount) throws Exception {
String name = TestConstructors.class.getName() + "$" + className + "::<init>";
Long count = methods.get(name);
if (count == null) {
throw new Exception("Could not find traced method " + name);
}
if (count != expectedCount) {
throw new Exception("Expected " + expectedCount + " trace event for " + name);
}
}
private static Map<String, Long> buildMethodMap(List<RecordedEvent> events) {
Map<String, Long> map = new TreeMap<>();
for (RecordedEvent e : events) {
RecordedMethod m = e.getValue("method");
String name = m.getType().getName() + "::" + m.getName();
map.compute(name, (_, value) -> (value == null) ? 1 : value + 1);
}
for (var e : map.entrySet()) {
System.out.println(e.getKey() + " " + e.getValue());
}
return map;
}
}

View File

@ -93,6 +93,8 @@ public class TestInstrumentation {
assertMethod(map, "exception", 2);
assertMethod(map, "switchExpression", 3);
assertMethod(map, "recursive", 4);
assertMethod(map, "deepException", 1);
assertMethod(map, "whileTrue", 1);
assertMethod(map, "multipleReturns", 5);
if (!map.isEmpty()) {
throw new Exception("Found unexpected methods " + map.keySet());
@ -105,6 +107,8 @@ public class TestInstrumentation {
assertMethod(map, "exception", 2);
assertMethod(map, "switchExpression", 3);
assertMethod(map, "recursive", 4);
assertMethod(map, "deepException", 1);
assertMethod(map, "whileTrue", 1);
assertMethod(map, "multipleReturns", 5);
for (var entry : map.entrySet()) {
long invocations = entry.getValue();

View File

@ -0,0 +1,69 @@
/*
* Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import javax.net.ssl.X509TrustManager;
import java.io.File;
import java.security.Security;
import java.time.LocalDate;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.util.Date;
/*
* @test
* @bug 8369282
* @summary Check that TLS Server certificates chaining back to distrusted
* Chunghwa root are invalid
* @library /test/lib
* @modules java.base/sun.security.validator
* @run main/othervm Chunghwa after policyOn invalid
* @run main/othervm Chunghwa after policyOff valid
* @run main/othervm Chunghwa before policyOn valid
* @run main/othervm Chunghwa before policyOff valid
*/
public class Chunghwa {
private static final String CERT_PATH = "chains" + File.separator + "chunghwa";
// The ePKI root has a test certificate chain stored in a file
// named "<root>-chain.pem".
private static final String ROOT_TO_TEST = "chunghwaepkirootca";
// Date after the restrictions take effect
private static final ZonedDateTime DISTRUST_DATE =
LocalDate.of(2026, 03, 18).atStartOfDay(ZoneOffset.UTC);
public static void main(String[] args) throws Exception {
Distrust distrust = new Distrust(args);
X509TrustManager[] tms = new X509TrustManager[]{
distrust.getTMF("PKIX", null),
distrust.getTMF("SunX509", null)
};
Date notBefore = distrust.getNotBefore(DISTRUST_DATE);
distrust.testCertificateChain(CERT_PATH, notBefore, tms, ROOT_TO_TEST);
}
}

View File

@ -0,0 +1,50 @@
Owner: CN=HiPKI Root CA - G1,
O="Chunghwa Telecom Co., Ltd.", C=TW
Issuer: OU=ePKI Root Certification Authority,
O="Chunghwa Telecom Co., Ltd.", C=TW
Serial number: 23fba648360e15e92ba78aedb67a0ae5
Valid from: Wed Dec 20 19:11:23 MST 2023 until: Tue Dec 19 08:59:59 MST 2034
Certificate fingerprints:
SHA1: 87:F1:DD:3B:8E:F1:E0:8C:A8:CA:CB:9B:CE:4E:26:5A:E4:4E:05:F2
SHA256: 68:07:C9:72:35:C5:EC:60:90:26:9A:4B:5F:ED:FA:B4:69:86:E4:2F:4D:67:D2:ED:DD:CF:6E:45:CF:0D:FA:80
Signature algorithm name: SHA256withRSA
Subject Public Key Algorithm: 4096-bit RSA key
Version: 3
-----BEGIN CERTIFICATE-----
MIIGjDCCBHSgAwIBAgIQI/umSDYOFekrp4rttnoK5TANBgkqhkiG9w0BAQsFADBe
MQswCQYDVQQGEwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0
ZC4xKjAoBgNVBAsMIWVQS0kgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe
Fw0yMzEyMjEwMjExMjNaFw0zNDEyMTkxNTU5NTlaME8xCzAJBgNVBAYTAlRXMSMw
IQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEbMBkGA1UEAwwSSGlQ
S0kgUm9vdCBDQSAtIEcxMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA
9B5/UnMyDHPkvRN0o9QwqNCuS9i233VHZvR85zkEHmpwINJaR3JnVfSl6J3VHiGh
8Ge6zCFovkRTv4354twvVcg3Px+kwJyz5HdcoEb+d/oaoDjq7Zpy3iu9lFc6uux5
5199QmQ5eiY29yTw1S+6lZgRZq2XNdZ1AYDgr/SEYYwNHl98h5ZeQa/rh+r4XfEu
iAU+TCK72h8q3VJGZDnzQs7ZngyzsHeXZJzA9KMuH5UHsBffMNsAGJZMoYFL3QRt
U6M9/Aes1MU3guvklQgZKILSQjqj2FPseYlgSGDIcpJQ3AOPgz+yQlda22rpEZfd
hSi8MEyr48KxRURHH+CKFgeW0iEPU8DtqX7UTuybCeyvQqww1r/REEXgphaypcXT
T3OUM3ECoWqj1jOXTyFjHluP2cFeRXF3D4FdXyGarYPM+l7WjSNfGz1BryB1ZlpK
9p/7qxj3ccC2HTHsOyDry+K49a6SsvfhhEvyovKTmiKe0xRvNlS9H15ZFblzqMF8
b3ti6RZsR1pl8w4Rm0bZ/W3c1pzAtH2lsN0/Vm+h+fbkEkj9Bn8SV7apI09bA8Pg
cSojt/ewsTu8mL3WmKgMa/aOEmem8rJY5AIJEzypuxC00jBF8ez3ABHfZfjcK0NV
vxaXxA/VLGGEqnKG/uY6fsI/fe78LxQ+5oXdUG+3Se0CAwEAAaOCAVMwggFPMB8G
A1UdIwQYMBaAFB4M97Zn8uGSJglFwFU5Lnc/QkqiMB0GA1UdDgQWBBTydxf6Xqj+
9j1x1Wi6yUYMONivsDAOBgNVHQ8BAf8EBAMCAYYwQAYDVR0fBDkwNzA1oDOgMYYv
aHR0cDovL2VjYS5oaW5ldC5uZXQvcmVwb3NpdG9yeS9DUkxfU0hBMi9DQS5jcmww
gYIGCCsGAQUFBwEBBHYwdDA7BggrBgEFBQcwAoYvaHR0cDovL2VjYS5oaW5ldC5u
ZXQvcmVwb3NpdG9yeS9DZXJ0cy9lQ0FHMS5jcnQwNQYIKwYBBQUHMAGGKWh0dHA6
Ly9vY3NwLmVjYS5oaW5ldC5uZXQvT0NTUC9vY3NwRzFzaGEyMBIGA1UdEwEB/wQI
MAYBAf8CAQEwIgYDVR0gBBswGTAIBgZngQwBAgIwDQYLKwYBBAGBtyNkAAMwDQYJ
KoZIhvcNAQELBQADggIBACY9pps8fqk3p8Xqv/qr26I1aFA4jOEG3VWd2bqn68Y9
InOMZozTMVh7iOnOfat7mEqn/RNhikvR5MOV3qAeg4gwgNb1OMuGltwfXWGiuGeT
vhimsV6E2hhJFAmZyXtfuoV9vSrnr1a5pCWqhVYWSCvoAQ/8Kv0tATKbIe21CYXz
NIo7O9QBSXt0BiaP9+CVQtJAYYuy2MNAcXgzgL4rownrYYAixhPmkxQE0Dt1gVbW
s2htBLJGse0z1fJDblY0Zar4t2ly+kIScx5DhRrrd8XKMK0YvID9Ythb+ao8m7Wd
Kymqr36benGL3GsvmSypLPlqZtfEqVITFhXwQiL8ruxoL+3WfNQJ09x0iV4xaP+E
bZSLLVzIiyhU49YdFHaqKyAJQvzgF2Za3DOwQWlP7OngtUx0ScEGHsoo78AM+Y0T
eLFxmr82kuyH18wZkUT9bLZlot11P2aC8VTprBGr+jEAMJjpmEjSA83ja/ttmqgh
qjj29Jnw3Lgy91XIhzBFMxMYo+hhYeBRmBFWl5+Y5oxBgPVLZpDJvg2rKa8xdqim
KgvF0DMKHntE0hhVy7JfUCnKovNQ0pf0NodLfjpqcCS2GBZ1mNcsW2MG2uBPANcn
LRXmt7N4XX11mctQTADwt8yZZ+2HDrST4kghOz+FXgftrPBdtDtM0T6WJcHWR1uS
-----END CERTIFICATE-----

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -149,7 +149,6 @@ public class ErrorTranslationTest extends ReplToolTesting {
return sb.toString();
}
@Test
public String getKind(Diagnostic.Kind kind) {
switch (kind) {
case WARNING:

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -44,7 +44,6 @@ import org.junit.jupiter.api.Test;
public class IdGeneratorTest {
@Test
public JShell.Builder getBuilder() {
TestingInputStream inStream = new TestingInputStream();
ByteArrayOutputStream outStream = new ByteArrayOutputStream();

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -32,13 +32,11 @@
import java.io.File;
import org.junit.jupiter.api.Assumptions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class KullaCompletenessStressTest extends CompletenessStressTest {
@Override
@Test
public File[] getDirectoriesToTest() {
String src = System.getProperty("test.src");
File file;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -57,6 +57,8 @@ abstract public class CDSAppTester {
private int numProductionRuns = 0;
private String whiteBoxJar = null;
private boolean inOneStepTraining = false;
private boolean generateBaseArchive = false;
private String[] baseArchiveOptions = new String[0];
/**
* All files created in the CDS/AOT workflow will be name + extension. E.g.
@ -343,7 +345,7 @@ abstract public class CDSAppTester {
// VM options used by this test, we need to create a temporary static archive to be used with -XX:ArchiveClassesAtExit.
private String getBaseArchiveForDynamicArchive() throws Exception {
WhiteBox wb = WhiteBox.getWhiteBox();
if (wb.isSharingEnabled()) {
if (wb.isSharingEnabled() && !generateBaseArchive) {
// This current JVM is able to use a default CDS archive included by the JDK, so
// if we launch a JVM child process (with the same set of options as the current JVM),
// that process is also able to use the same default CDS archive for creating
@ -356,6 +358,7 @@ abstract public class CDSAppTester {
if (!f.exists()) {
CDSOptions opts = new CDSOptions();
opts.setArchiveName(tempBaseArchiveFile);
opts.addSuffix(baseArchiveOptions);
opts.addSuffix("-Djava.class.path=");
OutputAnalyzer out = CDSTestUtils.createArchive(opts);
CDSTestUtils.checkBaseDump(out);
@ -364,6 +367,16 @@ abstract public class CDSAppTester {
}
}
public CDSAppTester setGenerateBaseArchive(boolean b) {
this.generateBaseArchive = b;
return this;
}
public CDSAppTester setBaseArchiveOptions(String... opts) {
this.baseArchiveOptions = opts;
return this;
}
private OutputAnalyzer dumpDynamicArchive() throws Exception {
RunMode runMode = RunMode.DUMP_DYNAMIC;
String[] cmdLine = new String[0];

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -58,9 +58,11 @@ public class SimpleCDSAppTester {
private String modulepath;
private String[] appCommandLine;
private String[] vmArgs = new String[] {};
private Tester tester;
private SimpleCDSAppTester(String name) {
this.name = name;
this.tester = new Tester(name);
}
public static SimpleCDSAppTester of(String name) {
@ -101,6 +103,16 @@ public class SimpleCDSAppTester {
return this;
}
public SimpleCDSAppTester setGenerateBaseArchive(boolean b) {
tester.setGenerateBaseArchive(b);
return this;
}
public SimpleCDSAppTester setBaseArchiveOptions(String... opts) {
tester.setBaseArchiveOptions(opts);
return this;
}
public SimpleCDSAppTester setTrainingChecker(BiConsumer<OutputAnalyzer, RunMode> checker) {
this.trainingChecker = checker;
return this;
@ -181,17 +193,22 @@ public class SimpleCDSAppTester {
}
public SimpleCDSAppTester runStaticWorkflow() throws Exception {
(new Tester(name)).runStaticWorkflow();
tester.runStaticWorkflow();
return this;
}
public SimpleCDSAppTester runDynamicWorkflow() throws Exception {
tester.runDynamicWorkflow();
return this;
}
public SimpleCDSAppTester runAOTWorkflow() throws Exception {
(new Tester(name)).runAOTWorkflow();
tester.runAOTWorkflow();
return this;
}
public SimpleCDSAppTester run(String args[]) throws Exception {
(new Tester(name)).run(args);
tester.run(args);
return this;
}
}

View File

@ -123,6 +123,12 @@ char* julong_to_string(julong value, char *string) {
return string;
}
static void
fatal(const char* msg) {
LOG("FATAL ERROR: %s\n", msg);
abort();
}
static void
fatal(JNIEnv* jni, const char* msg) {
jni->FatalError(msg);
@ -313,6 +319,17 @@ get_thread_name(jvmtiEnv *jvmti, JNIEnv* jni, jthread thread) {
return tname;
}
static char*
get_method_name(jvmtiEnv *jvmti, jmethodID method) {
char* mname = nullptr;
jvmtiError err;
err = jvmti->GetMethodName(method, &mname, nullptr, nullptr);
check_jvmti_error(err, "get_method_name: error in JVMTI GetMethodName call");
return mname;
}
static char*
get_method_name(jvmtiEnv *jvmti, JNIEnv* jni, jmethodID method) {
char* mname = nullptr;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -25,6 +25,7 @@ package org.openjdk.bench.java.io;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.RandomAccessFile;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
@ -81,4 +82,29 @@ public class FileWrite {
}
}
@State(Scope.Benchmark)
@Warmup(iterations = 3, time = 2)
@Measurement(iterations = 5, time = 5)
@BenchmarkMode(Mode.SampleTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Threads(1)
@Fork(value = 10)
public static class OpenFileForWritingBench {
final byte[] payload = "something".getBytes();
final String path = System.getProperty("os.name", "unknown").toLowerCase().contains("win") ? "NUL" : "/dev/null";
@Benchmark
public void testFileOutputStream() throws IOException {
try (FileOutputStream f = new FileOutputStream(path)) {
f.write(payload);
}
}
@Benchmark
public void testRandomAccessFile() throws IOException {
try (RandomAccessFile f = new RandomAccessFile(path, "rw")) {
f.write(payload);
}
}
}
}