mirror of
https://github.com/openjdk/jdk.git
synced 2026-05-04 18:55:22 +00:00
Merge branch 'openjdk:master' into cas-alloc-1
This commit is contained in:
commit
0b04841f33
2
.github/workflows/build-alpine-linux.yml
vendored
2
.github/workflows/build-alpine-linux.yml
vendored
@ -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 &&
|
||||
|
||||
2
.github/workflows/build-cross-compile.yml
vendored
2
.github/workflows/build-cross-compile.yml
vendored
@ -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 }} || (
|
||||
|
||||
2
.github/workflows/build-linux.yml
vendored
2
.github/workflows/build-linux.yml
vendored
@ -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 &&
|
||||
|
||||
2
.github/workflows/build-macos.yml
vendored
2
.github/workflows/build-macos.yml
vendored
@ -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 &&
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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.
|
||||
*/
|
||||
|
||||
@ -87,7 +87,7 @@ suppress.warnings=\
|
||||
@SuppressWarnings("rawtypes")\n
|
||||
|
||||
lint.category=\
|
||||
LintCategory.get({0}).get()
|
||||
LintCategory.{0}
|
||||
|
||||
diagnostic.flags.empty=\
|
||||
EnumSet.noneOf(DiagnosticFlag.class)
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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));
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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() {
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
@ -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.
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
@ -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() {
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -218,7 +218,7 @@ public:
|
||||
|
||||
virtual void record_success_concurrent();
|
||||
|
||||
virtual void record_success_degenerated();
|
||||
virtual void record_degenerated();
|
||||
|
||||
virtual void record_success_full();
|
||||
|
||||
|
||||
@ -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() {
|
||||
|
||||
@ -201,7 +201,7 @@ public:
|
||||
|
||||
void record_success_concurrent() override;
|
||||
|
||||
void record_success_degenerated() override;
|
||||
void record_degenerated() override;
|
||||
|
||||
void record_success_full() override;
|
||||
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -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() {}
|
||||
}
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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();
|
||||
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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() {
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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 ->
|
||||
"""
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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() {
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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);
|
||||
@ -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");
|
||||
}
|
||||
}
|
||||
@ -1 +0,0 @@
|
||||
policy.url.2=file:${test.src}/SecurityPropFile.policy
|
||||
@ -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"));
|
||||
}
|
||||
}
|
||||
@ -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");
|
||||
}
|
||||
}
|
||||
@ -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";
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
167
test/jdk/jdk/jfr/event/tracing/TestConstructors.java
Normal file
167
test/jdk/jdk/jfr/event/tracing/TestConstructors.java
Normal 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;
|
||||
}
|
||||
}
|
||||
@ -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();
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
@ -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-----
|
||||
@ -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:
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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];
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user