diff --git a/src/hotspot/cpu/ppc/c2_init_ppc.cpp b/src/hotspot/cpu/ppc/c2_init_ppc.cpp index d15f880e41375..e517cdf7de101 100644 --- a/src/hotspot/cpu/ppc/c2_init_ppc.cpp +++ b/src/hotspot/cpu/ppc/c2_init_ppc.cpp @@ -34,21 +34,5 @@ // Processor dependent initialization of C2 compiler for ppc. void Compile::pd_compiler2_init() { - - // Power7 and later. - if (PowerArchitecturePPC64 > 6) { - if (FLAG_IS_DEFAULT(UsePopCountInstruction)) { - FLAG_SET_ERGO(UsePopCountInstruction, true); - } - } - - if (!VM_Version::has_isel() && FLAG_IS_DEFAULT(ConditionalMoveLimit)) { - FLAG_SET_ERGO(ConditionalMoveLimit, 0); - } - - if (OptimizeFill) { - warning("OptimizeFill is not supported on this CPU."); - FLAG_SET_DEFAULT(OptimizeFill, false); - } - + guarantee(CodeEntryAlignment >= InteriorEntryAlignment, ""); } diff --git a/src/hotspot/cpu/ppc/vm_version_ppc.cpp b/src/hotspot/cpu/ppc/vm_version_ppc.cpp index 20578ed3b8baa..37e15548b4fb9 100644 --- a/src/hotspot/cpu/ppc/vm_version_ppc.cpp +++ b/src/hotspot/cpu/ppc/vm_version_ppc.cpp @@ -110,6 +110,17 @@ void VM_Version::initialize() { FLAG_SET_ERGO(TrapBasedRangeChecks, false); } + // Power7 and later. + if (PowerArchitecturePPC64 > 6) { + if (FLAG_IS_DEFAULT(UsePopCountInstruction)) { + FLAG_SET_ERGO(UsePopCountInstruction, true); + } + } + + if (!VM_Version::has_isel() && FLAG_IS_DEFAULT(ConditionalMoveLimit)) { + FLAG_SET_ERGO(ConditionalMoveLimit, 0); + } + if (PowerArchitecturePPC64 >= 8) { if (FLAG_IS_DEFAULT(SuperwordUseVSX)) { FLAG_SET_ERGO(SuperwordUseVSX, true); @@ -169,6 +180,17 @@ void VM_Version::initialize() { FLAG_SET_DEFAULT(UseByteReverseInstructions, false); } } + + if (OptimizeFill) { + warning("OptimizeFill is not supported on this CPU."); + FLAG_SET_DEFAULT(OptimizeFill, false); + } + + if (OptoScheduling) { + // The OptoScheduling information is not maintained in ppd.ad. + warning("OptoScheduling is not supported on this CPU."); + FLAG_SET_DEFAULT(OptoScheduling, false); + } #endif // Create and print feature-string. diff --git a/src/hotspot/cpu/s390/s390.ad b/src/hotspot/cpu/s390/s390.ad index 288de48c10586..561ffc9993cfa 100644 --- a/src/hotspot/cpu/s390/s390.ad +++ b/src/hotspot/cpu/s390/s390.ad @@ -2547,7 +2547,7 @@ operand uimmI8() %{ // operand type int // Unsigned Integer Immediate: 9-bit operand SSlenDW() %{ - predicate(Immediate::is_uimm8(n->get_long()-1)); + predicate(Immediate::is_uimm8((julong)n->get_long()-1)); match(ConL); op_cost(1); format %{ %} diff --git a/src/hotspot/os/aix/os_aix.cpp b/src/hotspot/os/aix/os_aix.cpp index 842ab0c6eebd6..44b9571e1024c 100644 --- a/src/hotspot/os/aix/os_aix.cpp +++ b/src/hotspot/os/aix/os_aix.cpp @@ -468,7 +468,7 @@ static void query_multipage_support() { // Can we use mmap with 64K pages? (Should be available with AIX7.3 TL1) { - void* p = mmap(NULL, 64*K, PROT_READ | PROT_WRITE, MAP_ANON_64K | MAP_ANONYMOUS | MAP_SHARED, -1, 0); + void* p = mmap(nullptr, 64*K, PROT_READ | PROT_WRITE, MAP_ANON_64K | MAP_ANONYMOUS | MAP_SHARED, -1, 0); assert(p != (void*) -1, "mmap failed"); if (p != (void*) -1) { g_multipage_support.can_use_64K_mmap_pages = (64*K == os::Aix::query_pagesize(p)); diff --git a/src/hotspot/os/linux/cgroupSubsystem_linux.cpp b/src/hotspot/os/linux/cgroupSubsystem_linux.cpp index d51499611a8d1..4a8fda432d894 100644 --- a/src/hotspot/os/linux/cgroupSubsystem_linux.cpp +++ b/src/hotspot/os/linux/cgroupSubsystem_linux.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 @@ -167,7 +167,7 @@ static bool find_ro_opt(char* mount_opts) { char* token; char* mo_ptr = mount_opts; // mount options are comma-separated (man proc). - while ((token = strsep(&mo_ptr, ",")) != NULL) { + while ((token = strsep(&mo_ptr, ",")) != nullptr) { if (strcmp(token, "ro") == 0) { return true; } diff --git a/src/hotspot/os/posix/os_posix.cpp b/src/hotspot/os/posix/os_posix.cpp index 75253843593c6..df11832ae95c8 100644 --- a/src/hotspot/os/posix/os_posix.cpp +++ b/src/hotspot/os/posix/os_posix.cpp @@ -816,7 +816,7 @@ void* os::dll_lookup(void* handle, const char* name) { void* ret = ::dlsym(handle, name); if (ret == nullptr) { const char* tmp = ::dlerror(); - // It is possible that we found a NULL symbol, hence no error. + // It is possible that we found a null symbol, hence no error. if (tmp != nullptr) { log_debug(os)("Symbol %s not found in dll: %s", name, tmp); } diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index 4dafef0c09823..40a022bbc174d 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -4150,7 +4150,7 @@ void getWindowsInstallationType(char* buffer, int bufferSize) { } // Query the value - if (RegQueryValueExA(hKey, valueName, NULL, NULL, (LPBYTE)buffer, &valueLength) != ERROR_SUCCESS) { + if (RegQueryValueExA(hKey, valueName, nullptr, nullptr, (LPBYTE)buffer, &valueLength) != ERROR_SUCCESS) { RegCloseKey(hKey); buffer[0] = '\0'; return; diff --git a/src/hotspot/share/cds/archiveUtils.cpp b/src/hotspot/share/cds/archiveUtils.cpp index 4622a27cbec72..430de362f9bf7 100644 --- a/src/hotspot/share/cds/archiveUtils.cpp +++ b/src/hotspot/share/cds/archiveUtils.cpp @@ -320,9 +320,8 @@ void WriteClosure::do_ptr(void** p) { void ReadClosure::do_ptr(void** p) { assert(*p == nullptr, "initializing previous initialized pointer."); intptr_t obj = nextPtr(); - assert((intptr_t)obj >= 0 || (intptr_t)obj < -100, - "hit tag while initializing ptrs."); - *p = (void*)obj != nullptr ? (void*)(SharedBaseAddress + obj) : (void*)obj; + assert(obj >= 0, "sanity."); + *p = (obj != 0) ? (void*)(_base_address + obj) : (void*)obj; } void ReadClosure::do_u4(u4* p) { diff --git a/src/hotspot/share/cds/archiveUtils.hpp b/src/hotspot/share/cds/archiveUtils.hpp index 410b0b8400196..f00895078ef1a 100644 --- a/src/hotspot/share/cds/archiveUtils.hpp +++ b/src/hotspot/share/cds/archiveUtils.hpp @@ -230,13 +230,14 @@ class WriteClosure : public SerializeClosure { class ReadClosure : public SerializeClosure { private: intptr_t** _ptr_array; - + intptr_t _base_address; inline intptr_t nextPtr() { return *(*_ptr_array)++; } public: - ReadClosure(intptr_t** ptr_array) { _ptr_array = ptr_array; } + ReadClosure(intptr_t** ptr_array, intptr_t base_address) : + _ptr_array(ptr_array), _base_address(base_address) {} void do_ptr(void** p); void do_u4(u4* p); diff --git a/src/hotspot/share/cds/filemap.cpp b/src/hotspot/share/cds/filemap.cpp index 223791cdd36f2..469f93d1e0cf5 100644 --- a/src/hotspot/share/cds/filemap.cpp +++ b/src/hotspot/share/cds/filemap.cpp @@ -274,6 +274,7 @@ void FileMapHeader::print(outputStream* st) { st->print_cr("- compressed_oops: %d", _compressed_oops); st->print_cr("- compressed_class_ptrs: %d", _compressed_class_ptrs); st->print_cr("- cloned_vtables_offset: " SIZE_FORMAT_X, _cloned_vtables_offset); + st->print_cr("- early_serialized_data_offset: " SIZE_FORMAT_X, _early_serialized_data_offset); st->print_cr("- serialized_data_offset: " SIZE_FORMAT_X, _serialized_data_offset); st->print_cr("- jvm_ident: %s", _jvm_ident); st->print_cr("- shared_path_table_offset: " SIZE_FORMAT_X, _shared_path_table_offset); diff --git a/src/hotspot/share/cds/filemap.hpp b/src/hotspot/share/cds/filemap.hpp index f7c2e9c19dee4..f3aa389c30e2a 100644 --- a/src/hotspot/share/cds/filemap.hpp +++ b/src/hotspot/share/cds/filemap.hpp @@ -193,6 +193,7 @@ class FileMapHeader: private CDSFileMapHeaderBase { bool _compressed_oops; // save the flag UseCompressedOops bool _compressed_class_ptrs; // save the flag UseCompressedClassPointers size_t _cloned_vtables_offset; // The address of the first cloned vtable + size_t _early_serialized_data_offset; // Data accessed using {ReadClosure,WriteClosure}::serialize() size_t _serialized_data_offset; // Data accessed using {ReadClosure,WriteClosure}::serialize() bool _has_non_jar_in_classpath; // non-jar file entry exists in classpath unsigned int _common_app_classpath_prefix_size; // size of the common prefix of app class paths @@ -261,6 +262,7 @@ class FileMapHeader: private CDSFileMapHeaderBase { uintx max_heap_size() const { return _max_heap_size; } CompressedOops::Mode narrow_oop_mode() const { return _narrow_oop_mode; } char* cloned_vtables() const { return from_mapped_offset(_cloned_vtables_offset); } + char* early_serialized_data() const { return from_mapped_offset(_early_serialized_data_offset); } char* serialized_data() const { return from_mapped_offset(_serialized_data_offset); } const char* jvm_ident() const { return _jvm_ident; } char* requested_base_address() const { return _requested_base_address; } @@ -283,6 +285,7 @@ class FileMapHeader: private CDSFileMapHeaderBase { void set_has_platform_or_app_classes(bool v) { _has_platform_or_app_classes = v; } void set_cloned_vtables(char* p) { set_as_offset(p, &_cloned_vtables_offset); } + void set_early_serialized_data(char* p) { set_as_offset(p, &_early_serialized_data_offset); } void set_serialized_data(char* p) { set_as_offset(p, &_serialized_data_offset); } void set_mapped_base_address(char* p) { _mapped_base_address = p; } void set_heap_root_segments(HeapRootSegments segments) { _heap_root_segments = segments; } @@ -396,6 +399,8 @@ class FileMapInfo : public CHeapObj { char* cloned_vtables() const { return header()->cloned_vtables(); } void set_cloned_vtables(char* p) const { header()->set_cloned_vtables(p); } + char* early_serialized_data() const { return header()->early_serialized_data(); } + void set_early_serialized_data(char* p) const { header()->set_early_serialized_data(p); } char* serialized_data() const { return header()->serialized_data(); } void set_serialized_data(char* p) const { header()->set_serialized_data(p); } diff --git a/src/hotspot/share/cds/metaspaceShared.cpp b/src/hotspot/share/cds/metaspaceShared.cpp index 2a43fd2dd4f2a..1d17fb7cfe352 100644 --- a/src/hotspot/share/cds/metaspaceShared.cpp +++ b/src/hotspot/share/cds/metaspaceShared.cpp @@ -359,8 +359,43 @@ void MetaspaceShared::read_extra_data(JavaThread* current, const char* filename) } } -// Read/write a data stream for restoring/preserving metadata pointers and -// miscellaneous data from/to the shared archive file. +// About "serialize" -- +// +// This is (probably a badly named) way to read/write a data stream of pointers and +// miscellaneous data from/to the shared archive file. The usual code looks like this: +// +// // These two global C++ variables are initialized during dump time. +// static int _archived_int; +// static MetaspaceObj* archived_ptr; +// +// void MyClass::serialize(SerializeClosure* soc) { +// soc->do_int(&_archived_int); +// soc->do_int(&_archived_ptr); +// } +// +// At dumptime, these two variables are stored into the CDS archive. +// At runtime, these two variables are loaded from the CDS archive. +// In addition, the pointer is relocated as necessary. +// +// Some of the xxx::serialize() functions may have side effects and assume that +// the archive is already mapped. For example, SymbolTable::serialize_shared_table_header() +// unconditionally makes the set of archived symbols available. Therefore, we put most +// of these xxx::serialize() functions inside MetaspaceShared::serialize(), which +// is called AFTER we made the decision to map the archive. +// +// However, some of the "serialized" data are used to decide whether an archive should +// be mapped or not (e.g., for checking if the -Djdk.module.main property is compatible +// with the archive). The xxx::serialize() functions for these data must be put inside +// MetaspaceShared::early_serialize(). Such functions must not produce side effects that +// assume we will always decides to map the archive. + +void MetaspaceShared::early_serialize(SerializeClosure* soc) { + int tag = 0; + soc->do_tag(--tag); + CDS_JAVA_HEAP_ONLY(Modules::serialize(soc);) + CDS_JAVA_HEAP_ONLY(Modules::serialize_addmods_names(soc);) + soc->do_tag(666); +} void MetaspaceShared::serialize(SerializeClosure* soc) { int tag = 0; @@ -402,8 +437,6 @@ void MetaspaceShared::serialize(SerializeClosure* soc) { SystemDictionaryShared::serialize_vm_classes(soc); soc->do_tag(--tag); - CDS_JAVA_HEAP_ONLY(Modules::serialize(soc);) - CDS_JAVA_HEAP_ONLY(Modules::serialize_addmods_names(soc);) CDS_JAVA_HEAP_ONLY(ClassLoaderDataShared::serialize(soc);) LambdaFormInvokers::serialize(soc); @@ -455,6 +488,7 @@ class VM_PopulateDumpSharedSpace : public VM_Operation { log_info(cds)("Dumping symbol table ..."); SymbolTable::write_to_archive(symbols); } + char* dump_early_read_only_tables(); char* dump_read_only_tables(); public: @@ -494,6 +528,21 @@ class StaticArchiveBuilder : public ArchiveBuilder { } }; +char* VM_PopulateDumpSharedSpace::dump_early_read_only_tables() { + ArchiveBuilder::OtherROAllocMark mark; + + // Write module name into archive + CDS_JAVA_HEAP_ONLY(Modules::dump_main_module_name();) + // Write module names from --add-modules into archive + CDS_JAVA_HEAP_ONLY(Modules::dump_addmods_names();) + + DumpRegion* ro_region = ArchiveBuilder::current()->ro_region(); + char* start = ro_region->top(); + WriteClosure wc(ro_region); + MetaspaceShared::early_serialize(&wc); + return start; +} + char* VM_PopulateDumpSharedSpace::dump_read_only_tables() { ArchiveBuilder::OtherROAllocMark mark; @@ -501,10 +550,7 @@ char* VM_PopulateDumpSharedSpace::dump_read_only_tables() { // Write lambform lines into archive LambdaFormInvokers::dump_static_archive_invokers(); - // Write module name into archive - CDS_JAVA_HEAP_ONLY(Modules::dump_main_module_name();) - // Write module names from --add-modules into archive - CDS_JAVA_HEAP_ONLY(Modules::dump_addmods_names();) + // Write the other data to the output array. DumpRegion* ro_region = ArchiveBuilder::current()->ro_region(); char* start = ro_region->top(); @@ -543,6 +589,7 @@ void VM_PopulateDumpSharedSpace::doit() { log_info(cds)("Make classes shareable"); _builder.make_klasses_shareable(); + char* early_serialized_data = dump_early_read_only_tables(); char* serialized_data = dump_read_only_tables(); SystemDictionaryShared::adjust_lambda_proxy_class_dictionary(); @@ -556,6 +603,7 @@ void VM_PopulateDumpSharedSpace::doit() { assert(static_archive != nullptr, "SharedArchiveFile not set?"); _map_info = new FileMapInfo(static_archive, true); _map_info->populate_header(MetaspaceShared::core_region_alignment()); + _map_info->set_early_serialized_data(early_serialized_data); _map_info->set_serialized_data(serialized_data); _map_info->set_cloned_vtables(CppVtables::vtables_serialized_base()); } @@ -1473,6 +1521,14 @@ MapArchiveResult MetaspaceShared::map_archive(FileMapInfo* mapinfo, char* mapped return MAP_ARCHIVE_OTHER_FAILURE; } + if (mapinfo->is_static()) { + // Currently, only static archive uses early serialized data. + char* buffer = mapinfo->early_serialized_data(); + intptr_t* array = (intptr_t*)buffer; + ReadClosure rc(&array, (intptr_t)mapped_base_address); + early_serialize(&rc); + } + mapinfo->set_is_mapped(true); return MAP_ARCHIVE_SUCCESS; } @@ -1509,7 +1565,7 @@ void MetaspaceShared::initialize_shared_spaces() { // shared string/symbol tables. char* buffer = static_mapinfo->serialized_data(); intptr_t* array = (intptr_t*)buffer; - ReadClosure rc(&array); + ReadClosure rc(&array, (intptr_t)SharedBaseAddress); serialize(&rc); // Finish up archived heap initialization. These must be @@ -1526,7 +1582,7 @@ void MetaspaceShared::initialize_shared_spaces() { FileMapInfo *dynamic_mapinfo = FileMapInfo::dynamic_info(); if (dynamic_mapinfo != nullptr) { intptr_t* buffer = (intptr_t*)dynamic_mapinfo->serialized_data(); - ReadClosure rc(&buffer); + ReadClosure rc(&buffer, (intptr_t)SharedBaseAddress); ArchiveBuilder::serialize_dynamic_archivable_items(&rc); DynamicArchive::setup_array_klasses(); dynamic_mapinfo->close(); diff --git a/src/hotspot/share/cds/metaspaceShared.hpp b/src/hotspot/share/cds/metaspaceShared.hpp index ecc158cc3efcf..0b4f6f2ecd401 100644 --- a/src/hotspot/share/cds/metaspaceShared.hpp +++ b/src/hotspot/share/cds/metaspaceShared.hpp @@ -111,6 +111,7 @@ class MetaspaceShared : AllStatic { static void unrecoverable_writing_error(const char* message = nullptr); static void writing_error(const char* message = nullptr); + static void early_serialize(SerializeClosure* sc) NOT_CDS_RETURN; static void serialize(SerializeClosure* sc) NOT_CDS_RETURN; // JVM/TI RedefineClasses() support: diff --git a/src/hotspot/share/classfile/classLoader.cpp b/src/hotspot/share/classfile/classLoader.cpp index 9a68e2640443f..cb155bdeb1939 100644 --- a/src/hotspot/share/classfile/classLoader.cpp +++ b/src/hotspot/share/classfile/classLoader.cpp @@ -1242,7 +1242,7 @@ static char decode_percent_encoded(const char *str, size_t& index) { hex[1] = str[index + 2]; hex[2] = '\0'; index += 2; - return (char) strtol(hex, NULL, 16); + return (char) strtol(hex, nullptr, 16); } return str[index]; } diff --git a/src/hotspot/share/classfile/modules.cpp b/src/hotspot/share/classfile/modules.cpp index 94e407d045fb5..2a8f8bd2424cc 100644 --- a/src/hotspot/share/classfile/modules.cpp +++ b/src/hotspot/share/classfile/modules.cpp @@ -599,6 +599,9 @@ void Modules::serialize(SerializeClosure* soc) { } log_info(cds)("optimized module handling: %s", CDSConfig::is_using_optimized_module_handling() ? "enabled" : "disabled"); log_info(cds)("full module graph: %s", CDSConfig::is_using_full_module_graph() ? "enabled" : "disabled"); + + // Don't hold onto the pointer, in case we might decide to unmap the archive. + _archived_main_module_name = nullptr; } } @@ -641,6 +644,9 @@ void Modules::serialize_addmods_names(SerializeClosure* soc) { } log_info(cds)("optimized module handling: %s", CDSConfig::is_using_optimized_module_handling() ? "enabled" : "disabled"); log_info(cds)("full module graph: %s", CDSConfig::is_using_full_module_graph() ? "enabled" : "disabled"); + + // Don't hold onto the pointer, in case we might decide to unmap the archive. + _archived_addmods_names = nullptr; } } diff --git a/src/hotspot/share/gc/g1/g1AnalyticsSequences.hpp b/src/hotspot/share/gc/g1/g1AnalyticsSequences.hpp index 4593c8d934df1..dbd13d29b78a3 100644 --- a/src/hotspot/share/gc/g1/g1AnalyticsSequences.hpp +++ b/src/hotspot/share/gc/g1/g1AnalyticsSequences.hpp @@ -35,6 +35,7 @@ class G1Predictions; // Container for TruncatedSeqs that need separate predictors by GC phase. class G1PhaseDependentSeq { TruncatedSeq _young_only_seq; + double _initial_value; TruncatedSeq _mixed_seq; NONCOPYABLE(G1PhaseDependentSeq); diff --git a/src/hotspot/share/gc/g1/g1AnalyticsSequences.inline.hpp b/src/hotspot/share/gc/g1/g1AnalyticsSequences.inline.hpp index d3520487caac9..02a54e2a0353b 100644 --- a/src/hotspot/share/gc/g1/g1AnalyticsSequences.inline.hpp +++ b/src/hotspot/share/gc/g1/g1AnalyticsSequences.inline.hpp @@ -34,6 +34,7 @@ bool G1PhaseDependentSeq::enough_samples_to_use_mixed_seq() const { G1PhaseDependentSeq::G1PhaseDependentSeq(int length) : _young_only_seq(length), + _initial_value(0.0), _mixed_seq(length) { } @@ -42,7 +43,7 @@ TruncatedSeq* G1PhaseDependentSeq::seq_raw(bool use_young_only_phase_seq) { } void G1PhaseDependentSeq::set_initial(double value) { - _young_only_seq.add(value); + _initial_value = value; } void G1PhaseDependentSeq::add(double value, bool for_young_only_phase) { @@ -51,8 +52,12 @@ void G1PhaseDependentSeq::add(double value, bool for_young_only_phase) { double G1PhaseDependentSeq::predict(const G1Predictions* predictor, bool use_young_only_phase_seq) const { if (use_young_only_phase_seq || !enough_samples_to_use_mixed_seq()) { + if (_young_only_seq.num() == 0) { + return _initial_value; + } return predictor->predict(&_young_only_seq); } else { + assert(_mixed_seq.num() > 0, "must not ask this with no samples"); return predictor->predict(&_mixed_seq); } } diff --git a/src/hotspot/share/include/cds.h b/src/hotspot/share/include/cds.h index af48c1a8c3554..4cc309dd9913d 100644 --- a/src/hotspot/share/include/cds.h +++ b/src/hotspot/share/include/cds.h @@ -69,7 +69,7 @@ typedef struct CDSFileMapRegion { size_t _ptrmap_offset; // Bitmap for relocating native pointer fields in archived heap objects. // (The base address is the bottom of the BM region). size_t _ptrmap_size_in_bits; - char* _mapped_base; // Actually mapped address (NULL if this region is not mapped). + char* _mapped_base; // Actually mapped address (null if this region is not mapped). } CDSFileMapRegion; // This portion of the archive file header must remain unchanged for diff --git a/src/hotspot/share/include/jvm.h b/src/hotspot/share/include/jvm.h index 6634306636b15..23040aa1dcd45 100644 --- a/src/hotspot/share/include/jvm.h +++ b/src/hotspot/share/include/jvm.h @@ -419,7 +419,7 @@ JVM_FindPrimitiveClass(JNIEnv *env, const char *utf); /* - * Find a class from a boot class loader. Returns NULL if class not found. + * Find a class from a boot class loader. Returns null if class not found. */ JNIEXPORT jclass JNICALL JVM_FindClassFromBootLoader(JNIEnv *env, const char *name); diff --git a/src/hotspot/share/oops/constantPool.cpp b/src/hotspot/share/oops/constantPool.cpp index 1c295e10b21db..7147e2588c965 100644 --- a/src/hotspot/share/oops/constantPool.cpp +++ b/src/hotspot/share/oops/constantPool.cpp @@ -477,7 +477,7 @@ void ConstantPool::remove_resolved_klass_if_non_deterministic(int cp_index) { if (k == nullptr) { // We'd come here if the referenced class has been excluded via // SystemDictionaryShared::is_excluded_class(). As a result, ArchiveBuilder - // has cleared the resolved_klasses()->at(...) pointer to NULL. Thus, we + // has cleared the resolved_klasses()->at(...) pointer to null. Thus, we // need to revert the tag to JVM_CONSTANT_UnresolvedClass. can_archive = false; } else { diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp index e7cc0a007665c..46a6e7719f3dc 100644 --- a/src/hotspot/share/oops/instanceKlass.cpp +++ b/src/hotspot/share/oops/instanceKlass.cpp @@ -2639,10 +2639,15 @@ void InstanceKlass::restore_unshareable_info(ClassLoaderData* loader_data, Handl // have been redefined. bool trace_name_printed = false; adjust_default_methods(&trace_name_printed); - vtable().initialize_vtable(); - itable().initialize_itable(); + if (verified_at_dump_time()) { + // Initialize vtable and itable for classes which can be verified at dump time. + // Unlinked classes such as old classes with major version < 50 cannot be verified + // at dump time. + vtable().initialize_vtable(); + itable().initialize_itable(); + } } -#endif +#endif // INCLUDE_JVMTI // restore constant pool resolved references constants()->restore_unshareable_info(CHECK); diff --git a/src/hotspot/share/opto/escape.cpp b/src/hotspot/share/opto/escape.cpp index f8a0209d9ad15..d16f778ea8462 100644 --- a/src/hotspot/share/opto/escape.cpp +++ b/src/hotspot/share/opto/escape.cpp @@ -644,7 +644,7 @@ bool ConnectionGraph::can_reduce_phi(PhiNode* ophi) const { // // 'curr_ctrl' is the control of the CastPP that we want to split through phi. // If the CastPP currently doesn't have a control then the CmpP/N will be -// against the NULL constant, otherwise it will be against the constant input of +// against the null constant, otherwise it will be against the constant input of // the existing CmpP/N. It's guaranteed that there will be a CmpP/N in the later // case because we have constraints on it and because the CastPP has a control // input. @@ -672,7 +672,7 @@ Node* ConnectionGraph::specialize_cmp(Node* base, Node* curr_ctrl) { // means that the CastPP now will be specific for a given base instead of a Phi. // An If-Then-Else-Region block is inserted to control the CastPP. The control // of the CastPP is a copy of the current one (if there is one) or a check -// against NULL. +// against null. // // Before: // @@ -806,10 +806,10 @@ Node* ConnectionGraph::split_castpp_load_through_phi(Node* curr_addp, Node* curr // After splitting the CastPP we'll put it under an If-Then-Else-Region control // flow. If the CastPP originally had an IfTrue/False control input then we'll // use a similar CmpP/N to control the new If-Then-Else-Region. Otherwise, we'll -// juse use a CmpP/N against the NULL constant. +// juse use a CmpP/N against the null constant. // // The If-Then-Else-Region isn't always needed. For instance, if input to -// splitted cast was not nullable (or if it was the NULL constant) then we don't +// splitted cast was not nullable (or if it was the null constant) then we don't // need (shouldn't) use a CastPP at all. // // After the casts are splitted we'll split the AddP->Loads through the Phi and @@ -837,7 +837,7 @@ Node* ConnectionGraph::split_castpp_load_through_phi(Node* curr_addp, Node* curr // // After (Very much simplified): // -// Call NULL +// Call Null // \ / // CmpP // | @@ -873,7 +873,7 @@ void ConnectionGraph::reduce_phi_on_castpp_field_load(Node* curr_castpp, Growabl // array, depending on the nullability status of the corresponding input in // ophi. // - // - nullptr: Meaning that the base is actually the NULL constant and therefore + // - nullptr: Meaning that the base is actually the null constant and therefore // we won't try to load from it. // // - CFG Node: Meaning that the base is a CastPP that was specialized for @@ -890,7 +890,7 @@ void ConnectionGraph::reduce_phi_on_castpp_field_load(Node* curr_castpp, Growabl if (base_t->maybe_null()) { if (base->is_Con()) { - // Nothing todo as bases_for_loads[i] is already nullptr + // Nothing todo as bases_for_loads[i] is already null } else { Node* new_castpp = specialize_castpp(curr_castpp, base, ophi->in(0)->in(i)); bases_for_loads.at_put(i, new_castpp->in(0)); // Use the ctrl of the new node just as a flag diff --git a/src/hotspot/share/opto/ifnode.cpp b/src/hotspot/share/opto/ifnode.cpp index 093cafd1574db..30834859d0338 100644 --- a/src/hotspot/share/opto/ifnode.cpp +++ b/src/hotspot/share/opto/ifnode.cpp @@ -1524,6 +1524,14 @@ Node* IfNode::Ideal(PhaseGVN *phase, bool can_reshape) { Node* prev_dom = search_identical(dist, igvn); if (prev_dom != nullptr) { + // Dominating CountedLoopEnd (left over from some now dead loop) will become the new loop exit. Outer strip mined + // loop will go away. Mark this loop as no longer strip mined. + if (is_CountedLoopEnd()) { + CountedLoopNode* counted_loop_node = as_CountedLoopEnd()->loopnode(); + if (counted_loop_node != nullptr) { + counted_loop_node->clear_strip_mined(); + } + } // Replace dominated IfNode return dominated_by(prev_dom, igvn, false); } diff --git a/src/hotspot/share/opto/library_call.cpp b/src/hotspot/share/opto/library_call.cpp index 523b1efd0c243..e3cd60e6d918a 100644 --- a/src/hotspot/share/opto/library_call.cpp +++ b/src/hotspot/share/opto/library_call.cpp @@ -7750,11 +7750,11 @@ bool LibraryCallKit::inline_intpoly_montgomeryMult_P256() { r = must_be_not_null(r, true); Node* a_start = array_element_address(a, intcon(0), T_LONG); - assert(a_start, "a array is NULL"); + assert(a_start, "a array is null"); Node* b_start = array_element_address(b, intcon(0), T_LONG); - assert(b_start, "b array is NULL"); + assert(b_start, "b array is null"); Node* r_start = array_element_address(r, intcon(0), T_LONG); - assert(r_start, "r array is NULL"); + assert(r_start, "r array is null"); Node* call = make_runtime_call(RC_LEAF | RC_NO_FP, OptoRuntime::intpoly_montgomeryMult_P256_Type(), @@ -7779,9 +7779,9 @@ bool LibraryCallKit::inline_intpoly_assign() { b = must_be_not_null(b, true); Node* a_start = array_element_address(a, intcon(0), T_LONG); - assert(a_start, "a array is NULL"); + assert(a_start, "a array is null"); Node* b_start = array_element_address(b, intcon(0), T_LONG); - assert(b_start, "b array is NULL"); + assert(b_start, "b array is null"); Node* call = make_runtime_call(RC_LEAF | RC_NO_FP, OptoRuntime::intpoly_assign_Type(), diff --git a/src/hotspot/share/opto/loopTransform.cpp b/src/hotspot/share/opto/loopTransform.cpp index 0ad60c80c2d6c..b8150ab302e0a 100644 --- a/src/hotspot/share/opto/loopTransform.cpp +++ b/src/hotspot/share/opto/loopTransform.cpp @@ -758,7 +758,6 @@ void PhaseIdealLoop::do_peeling(IdealLoopTree *loop, Node_List &old_new) { #endif } } - Node* entry = head->in(LoopNode::EntryControl); // Step 1: Clone the loop body. The clone becomes the peeled iteration. // The pre-loop illegally has 2 control users (old & new loops). diff --git a/src/hotspot/share/services/diagnosticFramework.cpp b/src/hotspot/share/services/diagnosticFramework.cpp index 73aa80a950f93..16f074c9cb503 100644 --- a/src/hotspot/share/services/diagnosticFramework.cpp +++ b/src/hotspot/share/services/diagnosticFramework.cpp @@ -424,7 +424,7 @@ bool DCmd::reorder_help_cmd(CmdLine line, stringStream &updated_line) { args.print("%s", line.args_addr()); char* rest = args.as_string(); char* token = strtok_r(rest, " ", &rest); - while (token != NULL) { + while (token != nullptr) { if (strcmp(token, "-h") == 0 || strcmp(token, "--help") == 0 || strcmp(token, "-help") == 0) { updated_line.print("%s", "help "); diff --git a/src/hotspot/share/utilities/concurrentHashTable.inline.hpp b/src/hotspot/share/utilities/concurrentHashTable.inline.hpp index 5656655275adb..74491e39ea99a 100644 --- a/src/hotspot/share/utilities/concurrentHashTable.inline.hpp +++ b/src/hotspot/share/utilities/concurrentHashTable.inline.hpp @@ -491,7 +491,7 @@ inline void ConcurrentHashTable:: Node* ndel_stack[StackBufferSize]; InternalTable* table = get_table(); assert(start_idx < stop_idx, "Must be"); - assert(stop_idx <= _table->_size, "Must be"); + assert(stop_idx <= _table->_size, "stop_idx %zu larger than table size %zu", stop_idx, _table->_size); // Here manual do critical section since we don't want to take the cost of // locking the bucket if there is nothing to delete. But we can have // concurrent single deletes. The _invisible_epoch can only be used by the @@ -1185,7 +1185,7 @@ inline bool ConcurrentHashTable:: do_scan_for_range(FUNC& scan_f, size_t start_idx, size_t stop_idx, InternalTable* table) { assert(start_idx < stop_idx, "Must be"); - assert(stop_idx <= table->_size, "Must be"); + assert(stop_idx <= table->_size, "stop_idx %zu larger than table size %zu", stop_idx, table->_size); for (size_t bucket_it = start_idx; bucket_it < stop_idx; ++bucket_it) { Bucket* bucket = table->get_bucket(bucket_it); diff --git a/src/java.base/macosx/native/libjli/java_md_macosx.m b/src/java.base/macosx/native/libjli/java_md_macosx.m index 354efc697690c..c836ae903e5f0 100644 --- a/src/java.base/macosx/native/libjli/java_md_macosx.m +++ b/src/java.base/macosx/native/libjli/java_md_macosx.m @@ -415,6 +415,8 @@ static void MacOSXStartup(int argc, char *argv[]) { { char libjava[MAXPATHLEN]; + JLI_TraceLauncher("Attempt to get JDK installation root from launcher executable path\n"); + if (GetApplicationHome(path, pathsize)) { /* Is the JDK co-located with the application? */ if (JLI_IsStaticallyLinked()) { @@ -429,18 +431,6 @@ static void MacOSXStartup(int argc, char *argv[]) { return JNI_TRUE; } } - /* ensure storage for path + /jre + NULL */ - if ((JLI_StrLen(path) + 4 + 1) > (size_t) pathsize) { - JLI_TraceLauncher("Insufficient space to store JRE path\n"); - return JNI_FALSE; - } - /* Does the app ship a private JRE in /jre directory? */ - JLI_Snprintf(libjava, sizeof(libjava), "%s/jre/lib/" JAVA_DLL, path); - if (access(libjava, F_OK) == 0) { - JLI_StrCat(path, "/jre"); - JLI_TraceLauncher("JRE path is %s\n", path); - return JNI_TRUE; - } } /* try to find ourselves instead */ diff --git a/src/java.base/share/classes/javax/crypto/KDF.java b/src/java.base/share/classes/javax/crypto/KDF.java index ea2a03758130d..0ee0904c1c2c4 100644 --- a/src/java.base/share/classes/javax/crypto/KDF.java +++ b/src/java.base/share/classes/javax/crypto/KDF.java @@ -396,19 +396,21 @@ public static KDF getInstance(String algorithm, InvalidAlgorithmParameterException { Objects.requireNonNull(algorithm, "algorithm must not be null"); Objects.requireNonNull(provider, "provider must not be null"); - - Instance instance = GetInstance.getInstance("KDF", KDFSpi.class, - algorithm, - kdfParameters, - provider); - if (!JceSecurity.canUseProvider(instance.provider)) { - String msg = "JCE cannot authenticate the provider " - + instance.provider.getName(); - throw new NoSuchProviderException(msg); + try { + Instance instance = GetInstance.getInstance("KDF", KDFSpi.class, + algorithm, + kdfParameters, + provider); + if (!JceSecurity.canUseProvider(instance.provider)) { + String msg = "JCE cannot authenticate the provider " + + instance.provider.getName(); + throw new NoSuchProviderException(msg); + } + return new KDF(new Delegate((KDFSpi) instance.impl, + instance.provider), algorithm); + } catch (NoSuchAlgorithmException nsae) { + return handleException(nsae); } - return new KDF(new Delegate((KDFSpi) instance.impl, - instance.provider), algorithm - ); } /** @@ -444,18 +446,31 @@ public static KDF getInstance(String algorithm, InvalidAlgorithmParameterException { Objects.requireNonNull(algorithm, "algorithm must not be null"); Objects.requireNonNull(provider, "provider must not be null"); - Instance instance = GetInstance.getInstance("KDF", KDFSpi.class, - algorithm, - kdfParameters, - provider); - if (!JceSecurity.canUseProvider(instance.provider)) { - String msg = "JCE cannot authenticate the provider " - + instance.provider.getName(); - throw new SecurityException(msg); + try { + Instance instance = GetInstance.getInstance("KDF", KDFSpi.class, + algorithm, + kdfParameters, + provider); + if (!JceSecurity.canUseProvider(instance.provider)) { + String msg = "JCE cannot authenticate the provider " + + instance.provider.getName(); + throw new SecurityException(msg); + } + return new KDF(new Delegate((KDFSpi) instance.impl, + instance.provider), algorithm); + } catch (NoSuchAlgorithmException nsae) { + return handleException(nsae); + } + } + + private static KDF handleException(NoSuchAlgorithmException e) + throws NoSuchAlgorithmException, + InvalidAlgorithmParameterException { + Throwable cause = e.getCause(); + if (cause instanceof InvalidAlgorithmParameterException iape) { + throw iape; } - return new KDF(new Delegate((KDFSpi) instance.impl, - instance.provider), algorithm - ); + throw e; } /** @@ -671,7 +686,8 @@ private static Delegate getNext(Iterator serviceIter, if (hasOne) throw new InvalidAlgorithmParameterException( "The KDFParameters supplied could not be used in combination " + "with the supplied algorithm for the selected Provider"); - else throw new NoSuchAlgorithmException(); + else throw new NoSuchAlgorithmException( + "No available provider supports the specified algorithm"); } private static boolean checkSpiNonNull(Delegate d) { diff --git a/src/java.base/share/classes/jdk/internal/foreign/ConfinedSession.java b/src/java.base/share/classes/jdk/internal/foreign/ConfinedSession.java index 432b324c1bd09..9b98bf82b5eee 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/ConfinedSession.java +++ b/src/java.base/share/classes/jdk/internal/foreign/ConfinedSession.java @@ -41,8 +41,7 @@ final class ConfinedSession extends MemorySessionImpl { private int asyncReleaseCount = 0; - static final VarHandle ASYNC_RELEASE_COUNT= MhUtil.findVarHandle( - MethodHandles.lookup(), "asyncReleaseCount", int.class); + static final VarHandle ASYNC_RELEASE_COUNT= MhUtil.findVarHandle(MethodHandles.lookup(), "asyncReleaseCount", int.class); public ConfinedSession(Thread owner) { super(owner, new ConfinedResourceList()); @@ -52,17 +51,17 @@ public ConfinedSession(Thread owner) { @ForceInline public void acquire0() { checkValidState(); - if (state == MAX_FORKS) { + if (acquireCount == MAX_FORKS) { throw tooManyAcquires(); } - state++; + acquireCount++; } @Override @ForceInline public void release0() { if (Thread.currentThread() == owner) { - state--; + acquireCount--; } else { // It is possible to end up here in two cases: this session was kept alive by some other confined session // which is implicitly released (in which case the release call comes from the cleaner thread). Or, @@ -75,11 +74,11 @@ public void release0() { void justClose() { checkValidState(); int asyncCount = (int)ASYNC_RELEASE_COUNT.getVolatile(this); - if ((state == 0 && asyncCount == 0) - || ((state - asyncCount) == 0)) { + int acquire = acquireCount - asyncCount; + if (acquire == 0) { state = CLOSED; } else { - throw alreadyAcquired(state - asyncCount); + throw alreadyAcquired(acquire); } } diff --git a/src/java.base/share/classes/jdk/internal/foreign/GlobalSession.java b/src/java.base/share/classes/jdk/internal/foreign/GlobalSession.java index c075778b5ee1d..3fc46d6c0bc3a 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/GlobalSession.java +++ b/src/java.base/share/classes/jdk/internal/foreign/GlobalSession.java @@ -42,6 +42,7 @@ non-sealed class GlobalSession extends MemorySessionImpl { public GlobalSession() { super(null, null); + this.state = NONCLOSEABLE; } @Override @@ -50,11 +51,6 @@ public void release0() { // do nothing } - @Override - public boolean isCloseable() { - return false; - } - @Override @ForceInline public void acquire0() { diff --git a/src/java.base/share/classes/jdk/internal/foreign/ImplicitSession.java b/src/java.base/share/classes/jdk/internal/foreign/ImplicitSession.java index 0eb3642508c09..0b79e45960a89 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/ImplicitSession.java +++ b/src/java.base/share/classes/jdk/internal/foreign/ImplicitSession.java @@ -42,6 +42,7 @@ final class ImplicitSession extends SharedSession { public ImplicitSession(Cleaner cleaner) { super(); + this.state = NONCLOSEABLE; cleaner.register(this, resourceList); } @@ -55,11 +56,6 @@ public void acquire0() { // do nothing } - @Override - public boolean isCloseable() { - return false; - } - @Override public void justClose() { throw nonCloseable(); diff --git a/src/java.base/share/classes/jdk/internal/foreign/MemorySessionImpl.java b/src/java.base/share/classes/jdk/internal/foreign/MemorySessionImpl.java index a12b16ca8b4fa..541a0907e4c60 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/MemorySessionImpl.java +++ b/src/java.base/share/classes/jdk/internal/foreign/MemorySessionImpl.java @@ -38,6 +38,7 @@ import jdk.internal.misc.ScopedMemoryAccess; import jdk.internal.invoke.MhUtil; import jdk.internal.vm.annotation.ForceInline; +import jdk.internal.vm.annotation.Stable; /** * This class manages the temporal bounds associated with a memory segment as well @@ -55,11 +56,19 @@ public abstract sealed class MemorySessionImpl implements Scope permits ConfinedSession, GlobalSession, SharedSession { + + /** + * The value of the {@code state} of a {@code MemorySessionImpl}. The only possible transition + * is OPEN -> CLOSED. As a result, the states CLOSED and NONCLOSEABLE are stable. This allows + * us to annotate {@code state} with {@link Stable} and elide liveness check on non-closeable + * constant scopes, such as {@code GLOBAL_SESSION}. + */ static final int OPEN = 0; static final int CLOSED = -1; + static final int NONCLOSEABLE = 1; - static final VarHandle STATE = MhUtil.findVarHandle( - MethodHandles.lookup(), "state", int.class); + static final VarHandle STATE = MhUtil.findVarHandle(MethodHandles.lookup(), "state", int.class); + static final VarHandle ACQUIRE_COUNT = MhUtil.findVarHandle(MethodHandles.lookup(), "acquireCount", int.class); static final int MAX_FORKS = Integer.MAX_VALUE; @@ -70,7 +79,11 @@ public abstract sealed class MemorySessionImpl final ResourceList resourceList; final Thread owner; - int state = OPEN; + + @Stable + int state; + + int acquireCount; public Arena asArena() { return new ArenaImpl(this); @@ -214,8 +227,8 @@ protected Object clone() throws CloneNotSupportedException { throw new CloneNotSupportedException(); } - public boolean isCloseable() { - return true; + public final boolean isCloseable() { + return state <= OPEN; } /** diff --git a/src/java.base/share/classes/jdk/internal/foreign/SharedSession.java b/src/java.base/share/classes/jdk/internal/foreign/SharedSession.java index 6c9666c2b58fc..b4415ad49590f 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/SharedSession.java +++ b/src/java.base/share/classes/jdk/internal/foreign/SharedSession.java @@ -44,6 +44,8 @@ sealed class SharedSession extends MemorySessionImpl permits ImplicitSession { private static final ScopedMemoryAccess SCOPED_MEMORY_ACCESS = ScopedMemoryAccess.getScopedMemoryAccess(); + private static final int CLOSED_ACQUIRE_COUNT = -1; + SharedSession() { super(null, new SharedResourceList()); } @@ -53,15 +55,15 @@ sealed class SharedSession extends MemorySessionImpl permits ImplicitSession { public void acquire0() { int value; do { - value = (int) STATE.getVolatile(this); - if (value < OPEN) { + value = (int) ACQUIRE_COUNT.getVolatile(this); + if (value < 0) { //segment is not open! - throw alreadyClosed(); + throw sharedSessionAlreadyClosed(); } else if (value == MAX_FORKS) { //overflow throw tooManyAcquires(); } - } while (!STATE.compareAndSet(this, value, value + 1)); + } while (!ACQUIRE_COUNT.compareAndSet(this, value, value + 1)); } @Override @@ -69,24 +71,35 @@ public void acquire0() { public void release0() { int value; do { - value = (int) STATE.getVolatile(this); - if (value <= OPEN) { + value = (int) ACQUIRE_COUNT.getVolatile(this); + if (value <= 0) { //cannot get here - we can't close segment twice - throw alreadyClosed(); + throw sharedSessionAlreadyClosed(); } - } while (!STATE.compareAndSet(this, value, value - 1)); + } while (!ACQUIRE_COUNT.compareAndSet(this, value, value - 1)); } void justClose() { - int prevState = (int) STATE.compareAndExchange(this, OPEN, CLOSED); - if (prevState < 0) { - throw alreadyClosed(); - } else if (prevState != OPEN) { - throw alreadyAcquired(prevState); + int acquireCount = (int) ACQUIRE_COUNT.compareAndExchange(this, 0, CLOSED_ACQUIRE_COUNT); + if (acquireCount < 0) { + throw sharedSessionAlreadyClosed(); + } else if (acquireCount > 0) { + throw alreadyAcquired(acquireCount); } + + STATE.setVolatile(this, CLOSED); SCOPED_MEMORY_ACCESS.closeScope(this, ALREADY_CLOSED); } + private IllegalStateException sharedSessionAlreadyClosed() { + // To avoid the situation where a scope fails to be acquired or closed but still reports as + // alive afterward, we wait for the state to change before throwing the exception + while ((int) STATE.getVolatile(this) == OPEN) { + Thread.onSpinWait(); + } + return alreadyClosed(); + } + /** * A shared resource list; this implementation has to handle add vs. add races, as well as add vs. cleanup races. */ diff --git a/src/java.base/unix/classes/sun/nio/fs/UnixConstants.java.template b/src/java.base/unix/classes/sun/nio/fs/UnixConstants.java.template index 828071482243d..7d2e73ea91544 100644 --- a/src/java.base/unix/classes/sun/nio/fs/UnixConstants.java.template +++ b/src/java.base/unix/classes/sun/nio/fs/UnixConstants.java.template @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -139,11 +139,13 @@ class UnixConstants { #endif // flags used with openat/unlinkat/etc. -#if defined(AT_SYMLINK_NOFOLLOW) && defined(AT_REMOVEDIR) +#if defined(AT_FDCWD) && defined(AT_SYMLINK_NOFOLLOW) && defined(AT_REMOVEDIR) + static final int PREFIX_AT_FDCWD = AT_FDCWD; static final int PREFIX_AT_SYMLINK_NOFOLLOW = AT_SYMLINK_NOFOLLOW; static final int PREFIX_AT_REMOVEDIR = AT_REMOVEDIR; #else // not supported (dummy values will not be used at runtime). + static final int PREFIX_AT_FDCWD = 00; static final int PREFIX_AT_SYMLINK_NOFOLLOW = 00; static final int PREFIX_AT_REMOVEDIR = 00; #endif diff --git a/src/java.base/unix/classes/sun/nio/fs/UnixFileAttributeViews.java b/src/java.base/unix/classes/sun/nio/fs/UnixFileAttributeViews.java index 94e0f91e81216..033deee2f4fda 100644 --- a/src/java.base/unix/classes/sun/nio/fs/UnixFileAttributeViews.java +++ b/src/java.base/unix/classes/sun/nio/fs/UnixFileAttributeViews.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -76,13 +76,16 @@ public void setTimes(FileTime lastModifiedTime, boolean useFutimes = false; boolean useFutimens = false; boolean useLutimes = false; + boolean useUtimensat = false; int fd = -1; try { if (!followLinks) { - useLutimes = lutimesSupported() && - UnixFileAttributes.get(file, false).isSymbolicLink(); + // these path-based syscalls also work if following links + if (!(useUtimensat = utimensatSupported())) { + useLutimes = lutimesSupported(); + } } - if (!useLutimes) { + if (!useUtimensat && !useLutimes) { fd = file.openForAttributeAccess(followLinks); if (fd != -1) { haveFd = true; @@ -92,8 +95,8 @@ public void setTimes(FileTime lastModifiedTime, } } } catch (UnixException x) { - if (!(x.errno() == UnixConstants.ENXIO || - (x.errno() == UnixConstants.ELOOP && useLutimes))) { + if (!(x.errno() == ENXIO || + (x.errno() == ELOOP && (useUtimensat || useLutimes)))) { x.rethrowAsIOException(file); } } @@ -117,7 +120,7 @@ public void setTimes(FileTime lastModifiedTime, } // update times - TimeUnit timeUnit = useFutimens ? + TimeUnit timeUnit = (useFutimens || useUtimensat) ? TimeUnit.NANOSECONDS : TimeUnit.MICROSECONDS; long modValue = lastModifiedTime.to(timeUnit); long accessValue= lastAccessTime.to(timeUnit); @@ -130,13 +133,16 @@ public void setTimes(FileTime lastModifiedTime, futimes(fd, accessValue, modValue); } else if (useLutimes) { lutimes(file, accessValue, modValue); + } else if (useUtimensat) { + utimensat(AT_FDCWD, file, accessValue, modValue, + followLinks ? 0 : AT_SYMLINK_NOFOLLOW); } else { utimes(file, accessValue, modValue); } } catch (UnixException x) { // if futimes/utimes fails with EINVAL and one/both of the times is // negative then we adjust the value to the epoch and retry. - if (x.errno() == UnixConstants.EINVAL && + if (x.errno() == EINVAL && (modValue < 0L || accessValue < 0L)) { retry = true; } else { @@ -153,6 +159,9 @@ public void setTimes(FileTime lastModifiedTime, futimes(fd, accessValue, modValue); } else if (useLutimes) { lutimes(file, accessValue, modValue); + } else if (useUtimensat) { + utimensat(AT_FDCWD, file, accessValue, modValue, + followLinks ? 0 : AT_SYMLINK_NOFOLLOW); } else { utimes(file, accessValue, modValue); } diff --git a/src/java.base/unix/classes/sun/nio/fs/UnixNativeDispatcher.java b/src/java.base/unix/classes/sun/nio/fs/UnixNativeDispatcher.java index ab8975c6d120d..d6d2b9fdcd719 100644 --- a/src/java.base/unix/classes/sun/nio/fs/UnixNativeDispatcher.java +++ b/src/java.base/unix/classes/sun/nio/fs/UnixNativeDispatcher.java @@ -391,6 +391,20 @@ static void lutimes(UnixPath path, long times0, long times1) private static native void lutimes0(long pathAddress, long times0, long times1) throws UnixException; + /** + * utimensat(int fd, const char* path, + * const struct timeval times[2], int flags) + */ + static void utimensat(int fd, UnixPath path, long times0, long times1, int flags) + throws UnixException + { + try (NativeBuffer buffer = copyToNativeBuffer(path)) { + utimensat0(fd, buffer.address(), times0, times1, flags); + } + } + private static native void utimensat0(int fd, long pathAddress, long times0, long times1, int flags) + throws UnixException; + /** * DIR *opendir(const char* dirname) */ @@ -557,7 +571,8 @@ static native int flistxattr(int filedes, long listAddress, int size) private static final int SUPPORTS_FUTIMES = 1 << 2; private static final int SUPPORTS_FUTIMENS = 1 << 3; private static final int SUPPORTS_LUTIMES = 1 << 4; - private static final int SUPPORTS_XATTR = 1 << 5; + private static final int SUPPORTS_UTIMENSAT = 1 << 5; + private static final int SUPPORTS_XATTR = 1 << 6; private static final int SUPPORTS_BIRTHTIME = 1 << 16; // other features private static final int capabilities; @@ -589,6 +604,13 @@ static boolean lutimesSupported() { return (capabilities & SUPPORTS_LUTIMES) != 0; } + /** + * Supports utimensat + */ + static boolean utimensatSupported() { + return (capabilities & SUPPORTS_UTIMENSAT) != 0; + } + /** * Supports file birth (creation) time attribute */ diff --git a/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c b/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c index 9a68a12c2198e..aa46a2470a104 100644 --- a/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c +++ b/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c @@ -211,6 +211,8 @@ typedef DIR* fdopendir_func(int); #if defined(__linux__) typedef int statx_func(int dirfd, const char *restrict pathname, int flags, unsigned int mask, struct my_statx *restrict statxbuf); +typedef int utimensat_func(int dirfd, const char *pathname, + const struct timespec[2], int flags); #endif static openat_func* my_openat_func = NULL; @@ -223,6 +225,7 @@ static lutimes_func* my_lutimes_func = NULL; static fdopendir_func* my_fdopendir_func = NULL; #if defined(__linux__) static statx_func* my_statx_func = NULL; +static utimensat_func* my_utimensat_func = NULL; #endif /** @@ -432,6 +435,10 @@ Java_sun_nio_fs_UnixNativeDispatcher_init(JNIEnv* env, jclass this) if (my_statx_func != NULL) { capabilities |= sun_nio_fs_UnixNativeDispatcher_SUPPORTS_BIRTHTIME; } + my_utimensat_func = (utimensat_func*) dlsym(RTLD_DEFAULT, "utimensat"); + if (my_utimensat_func != NULL) { + capabilities |= sun_nio_fs_UnixNativeDispatcher_SUPPORTS_UTIMENSAT; + } #endif /* supports extended attributes */ @@ -976,6 +983,34 @@ Java_sun_nio_fs_UnixNativeDispatcher_lutimes0(JNIEnv* env, jclass this, } } +JNIEXPORT void JNICALL +Java_sun_nio_fs_UnixNativeDispatcher_utimensat0(JNIEnv* env, jclass this, + jint fd, jlong pathAddress, jlong accessTime, jlong modificationTime, jint flags) { +#if defined(__linux__) + int err; + struct timespec times[2]; + const char* path = (const char*)jlong_to_ptr(pathAddress); + + times[0].tv_sec = accessTime / 1000000000; + times[0].tv_nsec = accessTime % 1000000000; + + times[1].tv_sec = modificationTime / 1000000000; + times[1].tv_nsec = modificationTime % 1000000000; + + if (my_utimensat_func == NULL) { + JNU_ThrowInternalError(env, "my_utimensat_func is NULL"); + return; + } + RESTARTABLE((*my_utimensat_func)(fd, path, ×[0], flags), err); + + if (err == -1) { + throwUnixException(env, errno); + } +#else + JNU_ThrowInternalError(env, "should not reach here"); +#endif +} + JNIEXPORT jlong JNICALL Java_sun_nio_fs_UnixNativeDispatcher_opendir0(JNIEnv* env, jclass this, jlong pathAddress) diff --git a/src/java.management/share/classes/com/sun/jmx/remote/internal/ServerNotifForwarder.java b/src/java.management/share/classes/com/sun/jmx/remote/internal/ServerNotifForwarder.java index 7ea1e48586915..f15c416f29635 100644 --- a/src/java.management/share/classes/com/sun/jmx/remote/internal/ServerNotifForwarder.java +++ b/src/java.management/share/classes/com/sun/jmx/remote/internal/ServerNotifForwarder.java @@ -169,7 +169,7 @@ public void removeNotificationListener(ObjectName name, } catch (Exception e) { // Give back the first exception // - if (re != null) { + if (re == null) { re = e; } } diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java index e35ecbdc95684..3545ebcc2780b 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java @@ -1672,6 +1672,12 @@ public boolean isCastable(Type t, Type s, Warner warn) { // where class DisjointChecker { Set> pairsSeen = new HashSet<>(); + /* there are three cases for ts and ss: + * - one is a class and the other one is an interface (case I) + * - both are classes (case II) + * - both are interfaces (case III) + * all those cases are covered in JLS 23, section: "5.1.6.1 Allowed Narrowing Reference Conversion" + */ private boolean areDisjoint(ClassSymbol ts, ClassSymbol ss) { Pair newPair = new Pair<>(ts, ss); /* if we are seeing the same pair again then there is an issue with the sealed hierarchy @@ -1679,32 +1685,38 @@ private boolean areDisjoint(ClassSymbol ts, ClassSymbol ss) { */ if (!pairsSeen.add(newPair)) return false; - if (isSubtype(erasure(ts.type), erasure(ss.type))) { - return false; - } - // if both are classes or both are interfaces, shortcut - if (ts.isInterface() == ss.isInterface() && isSubtype(erasure(ss.type), erasure(ts.type))) { - return false; - } - if (ts.isInterface() && !ss.isInterface()) { - /* so ts is interface but ss is a class - * an interface is disjoint from a class if the class is disjoint form the interface - */ - return areDisjoint(ss, ts); - } - // a final class that is not subtype of ss is disjoint - if (!ts.isInterface() && ts.isFinal()) { - return true; - } - // if at least one is sealed - if (ts.isSealed() || ss.isSealed()) { - // permitted subtypes have to be disjoint with the other symbol - ClassSymbol sealedOne = ts.isSealed() ? ts : ss; - ClassSymbol other = sealedOne == ts ? ss : ts; - return sealedOne.getPermittedSubclasses().stream().allMatch(type -> areDisjoint((ClassSymbol)type.tsym, other)); + + if (ts.isInterface() != ss.isInterface()) { // case I: one is a class and the other one is an interface + ClassSymbol isym = ts.isInterface() ? ts : ss; // isym is the interface and csym the class + ClassSymbol csym = isym == ts ? ss : ts; + if (!isSubtype(erasure(csym.type), erasure(isym.type))) { + if (csym.isFinal()) { + return true; + } else if (csym.isSealed()) { + return areDisjoint(isym, csym.getPermittedSubclasses()); + } else if (isym.isSealed()) { + // if the class is not final and not sealed then it has to be freely extensible + return areDisjoint(csym, isym.getPermittedSubclasses()); + } + } // now both are classes or both are interfaces + } else if (!ts.isInterface()) { // case II: both are classes + return !isSubtype(erasure(ss.type), erasure(ts.type)) && !isSubtype(erasure(ts.type), erasure(ss.type)); + } else { // case III: both are interfaces + if (!isSubtype(erasure(ts.type), erasure(ss.type)) && !isSubtype(erasure(ss.type), erasure(ts.type))) { + if (ts.isSealed()) { + return areDisjoint(ss, ts.getPermittedSubclasses()); + } else if (ss.isSealed()) { + return areDisjoint(ts, ss.getPermittedSubclasses()); + } + } } + // at this point we haven't been able to statically prove that the classes or interfaces are disjoint return false; } + + boolean areDisjoint(ClassSymbol csym, List permittedSubtypes) { + return permittedSubtypes.stream().allMatch(psubtype -> areDisjoint(csym, (ClassSymbol) psubtype.tsym)); + } } private TypeRelation isCastable = new TypeRelation() { diff --git a/test/hotspot/jtreg/TEST.groups b/test/hotspot/jtreg/TEST.groups index 2a08266d79ff3..575c0caa674c2 100644 --- a/test/hotspot/jtreg/TEST.groups +++ b/test/hotspot/jtreg/TEST.groups @@ -444,6 +444,7 @@ hotspot_appcds_dynamic = \ -runtime/cds/appcds/jcmd/JCmdTestStaticDump.java \ -runtime/cds/appcds/jcmd/JCmdTestDynamicDump.java \ -runtime/cds/appcds/jcmd/JCmdTestFileSafety.java \ + -runtime/cds/appcds/jvmti/redefineClasses/OldClassAndRedefineClass.java \ -runtime/cds/appcds/lambdaForm/DefaultClassListLFInvokers.java \ -runtime/cds/appcds/methodHandles \ -runtime/cds/appcds/sharedStrings \ diff --git a/test/hotspot/jtreg/compiler/loopstripmining/TestIdenticalDominatingCLE.java b/test/hotspot/jtreg/compiler/loopstripmining/TestIdenticalDominatingCLE.java new file mode 100644 index 0000000000000..371c0fb2bc57c --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopstripmining/TestIdenticalDominatingCLE.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2024, Red Hat, Inc. 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 8340532 + * @summary C2: assert(is_OuterStripMinedLoop()) failed: invalid node class: IfTrue + * @requires vm.compiler2.enabled + * @run main/othervm -XX:CompileOnly=TestIdenticalDominatingCLE::* -XX:CompileThreshold=100 -Xcomp -XX:-TieredCompilation + * -XX:-RangeCheckElimination -XX:LoopMaxUnroll=0 TestIdenticalDominatingCLE + * + */ + + +public class TestIdenticalDominatingCLE { + boolean bFld; + long lFld; + float[][] fArr = new float[6][6]; + + public static void main(String[] var0) { + TestIdenticalDominatingCLE t = new TestIdenticalDominatingCLE(); + t.test(); + } + + void test() { + int i = 0; + do { + for (int j = 0; j < 2; j++) { + float f = fArr[j][3] / Float.valueOf((float)1.318095814E9); + switch (i) { + case 1: + if (bFld ^ bFld) { + } else { + for (int k = 0; k < 600; k++) { + } + } + break; + default: + if (bFld) { + } + } + } + lFld = ++i; + } while (i < 6); + } +} diff --git a/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/BootChild.java b/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/BootChild.java new file mode 100644 index 0000000000000..08e15fea1a547 --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/BootChild.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +public class BootChild extends BootSuper { + // Does not override BootSuper::doit() +} diff --git a/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/BootSuper.java b/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/BootSuper.java new file mode 100644 index 0000000000000..d1682ebf3900c --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/BootSuper.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +public class BootSuper { + public String doit() { + return "Hello"; + } +} diff --git a/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/NewChild.java b/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/NewChild.java new file mode 100644 index 0000000000000..b11eb9717f175 --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/NewChild.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +public class NewChild extends OldSuper { + // Does not override BootSuper::doit() +} diff --git a/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/OldClassAndRedefineClass.java b/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/OldClassAndRedefineClass.java new file mode 100644 index 0000000000000..242a78ca024b6 --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/OldClassAndRedefineClass.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/* + * @test + * @bug 8342303 + * @summary Test loading of shared old class when another class has been redefined. + * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds /test/hotspot/jtreg/runtime/cds/appcds/test-classes /test/hotspot/jtreg/runtime/cds/appcds/jvmti + * @requires vm.cds.write.archived.java.heap + * @requires vm.jvmti + * @build jdk.test.whitebox.WhiteBox + * OldClassAndRedefineClassApp + * @compile ../../test-classes/OldSuper.jasm + * ../../test-classes/ChildOldSuper.java + * ../../test-classes/Hello.java + * @run driver RedefineClassHelper + * @run driver OldClassAndRedefineClass + */ + +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.helpers.ClassFileInstaller; + +public class OldClassAndRedefineClass { + public static String appClasses[] = { + "OldClassAndRedefineClassApp", + "OldSuper", + "ChildOldSuper", + "Hello", + }; + public static String sharedClasses[] = TestCommon.concat(appClasses); + + public static void main(String[] args) throws Throwable { + runTest(); + } + + public static void runTest() throws Throwable { + String appJar = + ClassFileInstaller.writeJar("OldClassAndRedefineClassApp.jar", appClasses); + + String agentCmdArg = "-javaagent:redefineagent.jar"; + + OutputAnalyzer out = TestCommon.testDump(appJar, sharedClasses, "-Xlog:cds,cds+class=debug"); + out.shouldMatch("klasses.*OldSuper.[*][*].unlinked") + .shouldMatch("klasses.*ChildOldSuper.[*][*].unlinked"); + + out = TestCommon.exec( + appJar, + "-XX:+UnlockDiagnosticVMOptions", + "-XX:+AllowArchivingWithJavaAgent", + "-XX:+WhiteBoxAPI", + "-Xlog:cds,class+load", + agentCmdArg, + "OldClassAndRedefineClassApp"); + out.shouldContain("[class,load] OldSuper source: shared objects file") + .shouldContain("[class,load] ChildOldSuper source: shared objects file") + .shouldContain("[class,load] Hello source: __VM_RedefineClasses__"); + } +} diff --git a/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/OldClassAndRedefineClassApp.java b/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/OldClassAndRedefineClassApp.java new file mode 100644 index 0000000000000..2c460ccb027fb --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/OldClassAndRedefineClassApp.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +public class OldClassAndRedefineClassApp { + + public static void main(String args[]) throws Throwable { + ClassLoader appClassLoader = ClassLoader.getSystemClassLoader(); + + System.out.println("Main: loading OldSuper"); + // Load an old class (version 49), but not linking it. + Class.forName("OldSuper", false, appClassLoader); + + // Redefine a class unrelated to the above old class. + System.out.println("INFO: instrumentation = " + RedefineClassHelper.instrumentation); + Class c = Class.forName("Hello", false, appClassLoader); + byte[] bytes = c.getClassLoader().getResourceAsStream(c.getName().replace('.', '/') + ".class").readAllBytes(); + RedefineClassHelper.redefineClass(c, bytes); + + System.out.println("Main: loading ChildOldSuper"); + // Load and link a subclass of the above old class. + // This will in turn link the old class and initializes its vtable, etc. + Class.forName("ChildOldSuper"); + } +} diff --git a/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/RedefineBootClassApp.java b/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/RedefineBootClassApp.java new file mode 100644 index 0000000000000..92642c467d2b7 --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/RedefineBootClassApp.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +import java.io.File; + +public class RedefineBootClassApp { + public static void main(String args[]) throws Throwable { + File bootJar = new File(args[0]); + + Class superCls = Class.forName("BootSuper", false, null); + System.out.println("BootSuper>> loader = " + superCls.getClassLoader()); + + { + BootSuper obj = (BootSuper)superCls.newInstance(); + System.out.println("(before transform) BootSuper>> doit() = " + obj.doit()); + } + + // Redefine the class + byte[] bytes = Util.getClassFileFromJar(bootJar, "BootSuper"); + Util.replace(bytes, "Hello", "HELLO"); + RedefineClassHelper.redefineClass(superCls, bytes); + + { + BootSuper obj = (BootSuper)superCls.newInstance(); + String s = obj.doit(); + System.out.println("(after transform) BootSuper>> doit() = " + s); + if (!s.equals("HELLO")) { + throw new RuntimeException("BootSuper doit() should be HELLO but got " + s); + } + } + + Class childCls = Class.forName("BootChild", false, null); + System.out.println("BootChild>> loader = " + childCls.getClassLoader()); + + + { + BootSuper obj = (BootSuper)childCls.newInstance(); + String s = obj.doit(); + System.out.println("(after transform) BootChild>> doit() = " + s); + if (!s.equals("HELLO")) { + throw new RuntimeException("BootChild doit() should be HELLO but got " + s); + } + } + } +} diff --git a/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/RedefineBootClassTest.java b/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/RedefineBootClassTest.java new file mode 100644 index 0000000000000..bc14ec996f598 --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/RedefineBootClassTest.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/* + * @test + * @bug 8342303 + * @summary Redefine a shared super class loaded by the boot loader. The vtable of its archived child class must be updated + * @library /test/lib + * /test/hotspot/jtreg/runtime/cds/appcds + * /test/hotspot/jtreg/runtime/cds/appcds/test-classes + * /test/hotspot/jtreg/runtime/cds/appcds/jvmti + * @requires vm.jvmti + * @build RedefineBootClassTest + * RedefineBootClassApp + * BootSuper BootChild + * @run driver RedefineClassHelper + * @run driver RedefineBootClassTest + */ + +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.helpers.ClassFileInstaller; + +public class RedefineBootClassTest { + public static String bootClasses[] = { + "BootSuper", + "BootChild", + }; + public static String appClasses[] = { + "RedefineBootClassApp", + "Util", + }; + public static String sharedClasses[] = TestCommon.concat(bootClasses, appClasses); + + public static void main(String[] args) throws Throwable { + runTest(); + } + + public static void runTest() throws Throwable { + String bootJar = + ClassFileInstaller.writeJar("RedefineClassBoot.jar", bootClasses); + String appJar = + ClassFileInstaller.writeJar("RedefineClassApp.jar", appClasses); + + String bootCP = "-Xbootclasspath/a:" + bootJar; + String agentCmdArg = "-javaagent:redefineagent.jar"; + + TestCommon.testDump(appJar, sharedClasses, bootCP, "-Xlog:cds,cds+class=debug"); + + OutputAnalyzer out = TestCommon.execAuto("-cp", appJar, + bootCP, + "-XX:+UnlockDiagnosticVMOptions", + "-Xlog:cds=info,class+load", + agentCmdArg, + "RedefineBootClassApp", bootJar); + out.reportDiagnosticSummary(); + TestCommon.checkExec(out); + } +} diff --git a/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/RedefineOldSuperApp.java b/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/RedefineOldSuperApp.java new file mode 100644 index 0000000000000..c60edfd28916e --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/RedefineOldSuperApp.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +import java.io.File; + +public class RedefineOldSuperApp { + public static void main(String args[]) throws Throwable { + File bootJar = new File(args[0]); + ClassLoader appClassLoader = ClassLoader.getSystemClassLoader(); + + Class superCls = Class.forName("OldSuper", false, appClassLoader); + System.out.println("OldSuper>> loader = " + superCls.getClassLoader()); + + { + OldSuper obj = (OldSuper)superCls.newInstance(); + System.out.println("(before transform) OldSuper>> doit() = " + obj.doit()); + } + + // Redefine the class + byte[] bytes = Util.getClassFileFromJar(bootJar, "OldSuper"); + Util.replace(bytes, "Hello", "HELLO"); + RedefineClassHelper.redefineClass(superCls, bytes); + + { + OldSuper obj = (OldSuper)superCls.newInstance(); + String s = obj.doit(); + System.out.println("(after transform) OldSuper>> doit() = " + s); + if (!s.equals("HELLO")) { + throw new RuntimeException("OldSuper doit() should be HELLO but got " + s); + } + } + + Class childCls = Class.forName("NewChild", false, appClassLoader); + System.out.println("NewChild>> loader = " + childCls.getClassLoader()); + + + { + OldSuper obj = (OldSuper)childCls.newInstance(); + String s = obj.doit(); + System.out.println("(after transform) NewChild>> doit() = " + s); + if (!s.equals("HELLO")) { + throw new RuntimeException("NewChild doit() should be HELLO but got " + s); + } + } + } +} diff --git a/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/RedefineOldSuperTest.java b/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/RedefineOldSuperTest.java new file mode 100644 index 0000000000000..a0c8fa7a44849 --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/appcds/jvmti/redefineClasses/RedefineOldSuperTest.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/* + * @test + * @bug 8342303 + * @summary Redefine a shared old super class loaded by the app loader. The vtable of its archived child class must be updated + * @library /test/lib + * /test/hotspot/jtreg/runtime/cds/appcds + * /test/hotspot/jtreg/runtime/cds/appcds/test-classes + * /test/hotspot/jtreg/runtime/cds/appcds/jvmti + * @requires vm.jvmti + * @compile ../../test-classes/OldSuper.jasm + * @build RedefineOldSuperTest + * RedefineOldSuperApp + * NewChild + * @run driver RedefineClassHelper + * @run driver RedefineOldSuperTest + */ + +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.helpers.ClassFileInstaller; + +public class RedefineOldSuperTest { + public static String appClasses[] = { + "OldSuper", + "NewChild", + "RedefineOldSuperApp", + "Util", + }; + public static String sharedClasses[] = TestCommon.concat(appClasses); + + public static void main(String[] args) throws Throwable { + runTest(); + } + + public static void runTest() throws Throwable { + String appJar = + ClassFileInstaller.writeJar("RedefineClassApp.jar", appClasses); + + String agentCmdArg = "-javaagent:redefineagent.jar"; + + TestCommon.testDump(appJar, sharedClasses, "-Xlog:cds,cds+class=debug"); + + OutputAnalyzer out = TestCommon.execAuto("-cp", appJar, + "-XX:+UnlockDiagnosticVMOptions", + "-Xlog:cds=info,class+load", + agentCmdArg, + "RedefineOldSuperApp", appJar); + out.reportDiagnosticSummary(); + TestCommon.checkExec(out); + } +} diff --git a/test/hotspot/jtreg/runtime/cds/appcds/redefineClass/RedefineBasicTest.java b/test/hotspot/jtreg/runtime/cds/appcds/redefineClass/RedefineBasicTest.java index acbd0c948bef2..fbdec462e095f 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/redefineClass/RedefineBasicTest.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/redefineClass/RedefineBasicTest.java @@ -30,7 +30,7 @@ * @requires vm.jvmti * @library /test/lib /test/hotspot/jtreg/serviceability/jvmti/RedefineClasses /test/hotspot/jtreg/runtime/cds/appcds * @run driver RedefineClassHelper - * @build jdk.test.whitebox.WhiteBox RedefineBasic + * @build jdk.test.whitebox.WhiteBox jdk.test.lib.compiler.InMemoryJavaCompiler RedefineBasic * @run driver RedefineBasicTest */ diff --git a/test/hotspot/jtreg/runtime/cds/appcds/redefineClass/RedefineRunningMethods_Shared.java b/test/hotspot/jtreg/runtime/cds/appcds/redefineClass/RedefineRunningMethods_Shared.java index 039aaef11cd13..62bd62662a053 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/redefineClass/RedefineRunningMethods_Shared.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/redefineClass/RedefineRunningMethods_Shared.java @@ -30,7 +30,7 @@ * @requires vm.jvmti * @library /test/lib /test/hotspot/jtreg/serviceability/jvmti/RedefineClasses /test/hotspot/jtreg/runtime/cds/appcds * @run driver RedefineClassHelper - * @build jdk.test.whitebox.WhiteBox + * @build jdk.test.whitebox.WhiteBox jdk.test.lib.compiler.InMemoryJavaCompiler * @compile RedefineRunningMethods_SharedHelper.java * @run driver RedefineRunningMethods_Shared */ diff --git a/test/hotspot/jtreg/runtime/logging/RedefineClasses.java b/test/hotspot/jtreg/runtime/logging/RedefineClasses.java index 34c8900e6162e..714c05174ebb3 100644 --- a/test/hotspot/jtreg/runtime/logging/RedefineClasses.java +++ b/test/hotspot/jtreg/runtime/logging/RedefineClasses.java @@ -30,6 +30,7 @@ * @modules java.compiler * java.instrument * @requires vm.jvmti + * @build jdk.test.lib.compiler.InMemoryJavaCompiler * @run main RedefineClassHelper * @run main/othervm -Xmx256m -XX:MaxMetaspaceSize=64m -javaagent:redefineagent.jar -Xlog:all=trace:file=all.log RedefineClasses */ diff --git a/test/hotspot/jtreg/serviceability/jvmti/GetMethodDeclaringClass/libTestUnloadedClass.cpp b/test/hotspot/jtreg/serviceability/jvmti/GetMethodDeclaringClass/libTestUnloadedClass.cpp index c32b787d57894..ad7708ba55d02 100644 --- a/test/hotspot/jtreg/serviceability/jvmti/GetMethodDeclaringClass/libTestUnloadedClass.cpp +++ b/test/hotspot/jtreg/serviceability/jvmti/GetMethodDeclaringClass/libTestUnloadedClass.cpp @@ -39,9 +39,9 @@ static std::atomic ring_buffer[BUFFER_SIZE]; void get_method_details(jmethodID method) { jclass method_class; - char *class_name = NULL; + char *class_name = nullptr; if (_jvmti->GetMethodDeclaringClass(method, &method_class) == JVMTI_ERROR_NONE) { - if (_jvmti->GetClassSignature(method_class, &class_name, NULL) == JVMTI_ERROR_NONE) { + if (_jvmti->GetClassSignature(method_class, &class_name, nullptr) == JVMTI_ERROR_NONE) { _jvmti->Deallocate((unsigned char *)class_name); } } @@ -49,14 +49,14 @@ void get_method_details(jmethodID method) { void* read_ringbuffer(void* arg) { JNIEnv *env; - _jvm->AttachCurrentThreadAsDaemon((void **)&env, NULL); + _jvm->AttachCurrentThreadAsDaemon((void **)&env, nullptr); for (;;) { jmethodID id = ring_buffer[rand() % BUFFER_SIZE].load(std::memory_order_relaxed); if (id != (jmethodID)0) { get_method_details(id); } } - return NULL; + return nullptr; } static void JNICALL ClassPrepareCallback(jvmtiEnv *jvmti_env, @@ -66,8 +66,8 @@ static void JNICALL ClassPrepareCallback(jvmtiEnv *jvmti_env, static bool reader_created = false; static int ring_buffer_idx = 0; - char *class_name = NULL; - if (jvmti_env->GetClassSignature(klass, &class_name, NULL) != JVMTI_ERROR_NONE) { + char *class_name = nullptr; + if (jvmti_env->GetClassSignature(klass, &class_name, nullptr) != JVMTI_ERROR_NONE) { return; } // We only care MyClass and only one thread loads it @@ -79,7 +79,7 @@ static void JNICALL ClassPrepareCallback(jvmtiEnv *jvmti_env, if (!reader_created) { pthread_t tid; - pthread_create(&tid, NULL, read_ringbuffer, NULL); + pthread_create(&tid, nullptr, read_ringbuffer, nullptr); reader_created = true; } @@ -119,7 +119,7 @@ JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) } // Enable the ClassPrepare event - error = _jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_CLASS_PREPARE, NULL); + error = _jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_CLASS_PREPARE, nullptr); if (error != JVMTI_ERROR_NONE) { fprintf(stderr, "Error enabling ClassPrepare event: %d\n", error); return JNI_ERR; diff --git a/test/hotspot/jtreg/serviceability/jvmti/vthread/VThreadEventTest/libVThreadEventTest.cpp b/test/hotspot/jtreg/serviceability/jvmti/vthread/VThreadEventTest/libVThreadEventTest.cpp index c97a8ef3471aa..13ff93de9dc25 100644 --- a/test/hotspot/jtreg/serviceability/jvmti/vthread/VThreadEventTest/libVThreadEventTest.cpp +++ b/test/hotspot/jtreg/serviceability/jvmti/vthread/VThreadEventTest/libVThreadEventTest.cpp @@ -118,13 +118,13 @@ Agent_OnAttach(JavaVM *vm, char *options, void *reserved) { } clazz = env->FindClass("VThreadEventTest"); - if (clazz == NULL) { + if (clazz == nullptr) { LOG("FindClass failed\n"); return JNI_ERR; } mid = env->GetStaticMethodID(clazz, "agentStarted", "()V"); - if (mid == NULL) { + if (mid == nullptr) { LOG("GetStaticMethodID failed\n"); return JNI_ERR; } diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 59d86c646d230..1ae9623ef14c2 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -773,6 +773,7 @@ jdk/incubator/vector/LoadJsvmlTest.java 8305390 windows- # jdk_jfr jdk/jfr/event/compiler/TestCodeSweeper.java 8338127 generic-all +jdk/jfr/event/oldobject/TestShenandoah.java 8342951 generic-all jdk/jfr/event/runtime/TestResidentSetSizeEvent.java 8309846 aix-ppc64 jdk/jfr/jvm/TestWaste.java 8282427 generic-all @@ -806,6 +807,7 @@ java/awt/image/VolatileImage/VolatileImageConfigurationTest.java 8171069 macosx- java/awt/Modal/InvisibleParentTest/InvisibleParentTest.java 8172245 linux-all java/awt/Frame/FrameStateTest/FrameStateTest.java 8203920 macosx-all,linux-all java/awt/print/PrinterJob/ScaledText/ScaledText.java 8231226 macosx-all +java/awt/print/PrinterJob/PrintTextTest.java 8148334 generic-all java/awt/font/TextLayout/TestJustification.java 8250791 macosx-all java/awt/TrayIcon/DragEventSource/DragEventSource.java 8252242 macosx-all java/awt/FileDialog/DefaultFocusOwner/DefaultFocusOwner.java 7187728 macosx-all,linux-all diff --git a/test/jdk/TEST.groups b/test/jdk/TEST.groups index e7ee8990f94fb..4ac340ad3a33d 100644 --- a/test/jdk/TEST.groups +++ b/test/jdk/TEST.groups @@ -670,4 +670,4 @@ jdk_core_no_security = \ # Set of tests for `@since` checks in source code documentation jdk_since_checks = \ - tools/sincechecker/modules/java_base/CheckSince_javaBase.java + tools/sincechecker/ diff --git a/test/jdk/com/sun/crypto/provider/KDF/HKDFExhaustiveTest.java b/test/jdk/com/sun/crypto/provider/KDF/HKDFExhaustiveTest.java index 0088fe54a80de..fd33337a3c015 100644 --- a/test/jdk/com/sun/crypto/provider/KDF/HKDFExhaustiveTest.java +++ b/test/jdk/com/sun/crypto/provider/KDF/HKDFExhaustiveTest.java @@ -69,6 +69,8 @@ public class HKDFExhaustiveTest { private static final int LARGE_LENGTH = 1000; private static final int NEGATIVE_LENGTH = -1; + static class TestKDFParams implements KDFParameters {} + private static final KdfVerifier KdfGetInstanceVerifier = (a, p, s) -> { @@ -304,6 +306,12 @@ private static void testGetInstanceNegative() { Utils.runAndCheckException( () -> KDF.getInstance(KDF_ALGORITHMS[0], null, INVALID_STRING), NoSuchProviderException.class); + Utils.runAndCheckException( + () -> KDF.getInstance(KDF_ALGORITHMS[0], new TestKDFParams(), SUNJCE), + InvalidAlgorithmParameterException.class); + Utils.runAndCheckException( + () -> KDF.getInstance(KDF_ALGORITHMS[0], new TestKDFParams(), SUNJCE_PROVIDER), + InvalidAlgorithmParameterException.class); // getInstance(String algorithm, KDFParameters kdfParameters, Provider provider) Utils.runAndCheckException( diff --git a/test/jdk/java/awt/print/PrinterJob/PrintTextTest.java b/test/jdk/java/awt/print/PrinterJob/PrintTextTest.java index 95bf177aa2f11..f2ec4e15a8aae 100644 --- a/test/jdk/java/awt/print/PrinterJob/PrintTextTest.java +++ b/test/jdk/java/awt/print/PrinterJob/PrintTextTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 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 @@ -21,193 +21,207 @@ * questions. */ -/** +/* * @test * @bug 6425068 7157659 8132890 * @key printer * @summary Confirm that text prints where we expect to the length we expect. - * @run main/manual=yesno PrintTextTest + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual PrintTextTest */ -import java.awt.*; -import java.awt.event.*; -import java.text.*; -import java.util.*; -import java.awt.font.*; -import java.awt.geom.*; -import java.awt.print.*; -import javax.swing.*; - -public class PrintTextTest extends Component implements Printable { - - static int preferredSize; - Font textFont; - AffineTransform gxTx; - String page; - boolean useFM; - - public static void main(String args[]) { - String[] instructions = - { - "This tests that printed text renders similarly to on-screen", - "under a variety of APIs and graphics and font transforms", - "Print to your preferred printer. Collect the output.", - "Refer to the onscreen buttons to cycle through the on-screen", - "content", - "For each page, confirm that the printed content corresponds to", - "the on-screen rendering for that *same* page.", - "Some cases may look odd but its intentional. Verify", - "it looks the same on screen and on the printer.", - "Note that text does not scale linearly from screen to printer", - "so some differences are normal and not a bug.", - "The easiest way to spot real problems is to check that", - "any underlines are the same length as the underlined text", - "and that any rotations are the same in each case.", - "Note that each on-screen page is printed in both portrait", - "and landscape mode", - "So for example, Page 1/Portrait, and Page 1/Landscape when", - "rotated to view properly, should both match Page 1 on screen.", - }; - Sysout.createDialogWithInstructions(instructions); - +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GraphicsEnvironment; +import java.awt.RenderingHints; +import java.awt.font.FontRenderContext; +import java.awt.font.GlyphVector; +import java.awt.font.TextLayout; +import java.awt.geom.AffineTransform; +import java.awt.geom.Point2D; +import java.awt.print.Book; +import java.awt.print.PageFormat; +import java.awt.print.Printable; +import java.awt.print.PrinterException; +import java.awt.print.PrinterJob; +import java.text.AttributedCharacterIterator; +import java.text.AttributedString; +import java.util.HashMap; + +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JTabbedPane; + +public class PrintTextTest { + + static final String INSTRUCTIONS = """ + This tests that printed text renders similarly to on-screen under a variety + of APIs and graphics and font transforms. + 1. Print to your preferred printer. + 2. Collect the output. + 3. Refer to the onscreen buttons to cycle through the on-screen content. + 4. For each page, confirm that the printed content corresponds to the + on-screen rendering for that *same* page. Some cases may look odd but + its intentional. Verify it looks the same on screen and on the printer. + Note that text does not scale linearly from screen to printer so some + differences are normal and not a bug. + The easiest way to spot real problems is to check that any underlines are + the same length as the underlined text and that any rotations are the same + in each case. + Note that each on-screen page is printed in both portrait and landscape mode. + So for example, Page 1/Portrait, and Page 1/Landscape when rotated to view + properly, should both match Page 1 on screen. + """; + + public static void main(String[] args) throws Exception { PrinterJob pjob = PrinterJob.getPrinterJob(); PageFormat portrait = pjob.defaultPage(); portrait.setOrientation(PageFormat.PORTRAIT); - preferredSize = (int)portrait.getImageableWidth(); + int preferredSize = (int) portrait.getImageableWidth(); PageFormat landscape = pjob.defaultPage(); landscape.setOrientation(PageFormat.LANDSCAPE); Book book = new Book(); - JTabbedPane p = new JTabbedPane(); + JTabbedPane pane = new JTabbedPane(); int page = 1; - Font font = new Font("Dialog", Font.PLAIN, 18); - String name = "Page " + new Integer(page++); - PrintTextTest ptt = new PrintTextTest(name, font, null, false); - p.add(name, ptt); - book.append(ptt, portrait); - book.append(ptt, landscape); - - font = new Font("Dialog", Font.PLAIN, 18); - name = "Page " + new Integer(page++); - ptt = new PrintTextTest(name, font, null, true); - p.add(name, ptt); - book.append(ptt, portrait); - book.append(ptt, landscape); + Font font = new Font(Font.DIALOG, Font.PLAIN, 18); + String name = "Page " + page++; + PrintText pt = new PrintText(name, font, null, false, preferredSize); + pane.addTab(name, pt); + book.append(pt, portrait); + book.append(pt, landscape); + + font = new Font(Font.DIALOG, Font.PLAIN, 18); + name = "Page " + page++; + pt = new PrintText(name, font, null, true, preferredSize); + pane.addTab(name, pt); + book.append(pt, portrait); + book.append(pt, landscape); font = getPhysicalFont(); - name = "Page " + new Integer(page++); - ptt = new PrintTextTest(name, font, null, false); - p.add(name, ptt); - book.append(ptt, portrait); - book.append(ptt, landscape); + name = "Page " + page++; + pt = new PrintText(name, font, null, false, preferredSize); + pane.addTab(name, pt); + book.append(pt, portrait); + book.append(pt, landscape); font = getPhysicalFont(); AffineTransform rotTx = AffineTransform.getRotateInstance(0.15); - rotTx.translate(60,0); - name = "Page " + new Integer(page++); - ptt = new PrintTextTest(name, font, rotTx, false); - p.add(name, ptt); - book.append(ptt, portrait); - book.append(ptt, landscape); - - font = new Font("Dialog", Font.PLAIN, 18); + rotTx.translate(60, 0); + name = "Page " + page++; + pt = new PrintText(name, font, rotTx, false, preferredSize); + pane.addTab(name, pt); + book.append(pt, portrait); + book.append(pt, landscape); + + font = new Font(Font.DIALOG, Font.PLAIN, 18); AffineTransform scaleTx = AffineTransform.getScaleInstance(1.25, 1.25); - name = "Page " + new Integer(page++); - ptt = new PrintTextTest(name, font, scaleTx, false); - p.add(name, ptt); - book.append(ptt, portrait); - book.append(ptt, landscape); + name = "Page " + page++; + pt = new PrintText(name, font, scaleTx, false, preferredSize); + pane.addTab(name, pt); + book.append(pt, portrait); + book.append(pt, landscape); - font = new Font("Dialog", Font.PLAIN, 18); + font = new Font(Font.DIALOG, Font.PLAIN, 18); scaleTx = AffineTransform.getScaleInstance(-1.25, 1.25); - scaleTx.translate(-preferredSize/1.25, 0); - name = "Page " + new Integer(page++); - ptt = new PrintTextTest(name, font, scaleTx, false); - p.add(name, ptt); - book.append(ptt, portrait); - book.append(ptt, landscape); - - font = new Font("Dialog", Font.PLAIN, 18); + scaleTx.translate(-preferredSize / 1.25, 0); + name = "Page " + page++; + pt = new PrintText(name, font, scaleTx, false, preferredSize); + pane.addTab(name, pt); + book.append(pt, portrait); + book.append(pt, landscape); + + font = new Font(Font.DIALOG, Font.PLAIN, 18); scaleTx = AffineTransform.getScaleInstance(1.25, -1.25); - scaleTx.translate(0, -preferredSize/1.25); - name = "Page " + new Integer(page++); - ptt = new PrintTextTest(name, font, scaleTx, false); - p.add(name, ptt); - book.append(ptt, portrait); - book.append(ptt, landscape); + scaleTx.translate(0, -preferredSize / 1.25); + name = "Page " + page++; + pt = new PrintText(name, font, scaleTx, false, preferredSize); + pane.addTab(name, pt); + book.append(pt, portrait); + book.append(pt, landscape); font = font.deriveFont(rotTx); - name = "Page " + new Integer(page++); - ptt = new PrintTextTest(name, font, null, false); - p.add(ptt, BorderLayout.CENTER); - p.add(name, ptt); - book.append(ptt, portrait); - book.append(ptt, landscape); - - font = new Font("Monospaced", Font.PLAIN, 12); - name = "Page " + new Integer(page++); - ptt = new PrintTextTest(name, font, null, false); - p.add(ptt, BorderLayout.CENTER); - p.add(name, ptt); - book.append(ptt, portrait); - book.append(ptt, landscape); + name = "Page " + page++; + pt = new PrintText(name, font, null, false, preferredSize); + pane.addTab(name, pt); + book.append(pt, portrait); + book.append(pt, landscape); + + font = new Font(Font.MONOSPACED, Font.PLAIN, 12); + name = "Page " + page++; + pt = new PrintText(name, font, null, false, preferredSize); + pane.addTab(name, pt); + book.append(pt, portrait); + book.append(pt, landscape); Font xfont = font.deriveFont(AffineTransform.getScaleInstance(1.5, 1)); - name = "Page " + new Integer(page++); - ptt = new PrintTextTest(name, xfont, null, false); - p.add(ptt, BorderLayout.CENTER); - p.add(name, ptt); - book.append(ptt, portrait); - book.append(ptt, landscape); + name = "Page " + page++; + pt = new PrintText(name, xfont, null, false, preferredSize); + pane.addTab(name, pt); + book.append(pt, portrait); + book.append(pt, landscape); Font yfont = font.deriveFont(AffineTransform.getScaleInstance(1, 1.5)); - name = "Page " + new Integer(page++); - ptt = new PrintTextTest(name, yfont, null, false); - p.add(ptt, BorderLayout.CENTER); - p.add(name, ptt); - book.append(ptt, portrait); - book.append(ptt, landscape); + name = "Page " + page++; + pt = new PrintText(name, yfont, null, false, preferredSize); + pane.addTab(name, pt); + book.append(pt, portrait); + book.append(pt, landscape); if (System.getProperty("os.name").startsWith("Windows")) { font = new Font("MS Gothic", Font.PLAIN, 12); - name = "Page " + new Integer(page++); - ptt = new PrintJAText(name, font, null, true); - p.add(ptt, BorderLayout.CENTER); - p.add(name, ptt); - book.append(ptt, portrait); - book.append(ptt, landscape); + name = "Page " + page++; + pt = new PrintJapaneseText(name, font, null, true, preferredSize); + pane.addTab(name, pt); + book.append(pt, portrait); + book.append(pt, landscape); font = new Font("MS Gothic", Font.PLAIN, 12); - name = "Page " + new Integer(page++); + name = "Page " + page++; rotTx = AffineTransform.getRotateInstance(0.15); - ptt = new PrintJAText(name, font, rotTx, true); - p.add(ptt, BorderLayout.CENTER); - p.add(name, ptt); - book.append(ptt, portrait); - book.append(ptt, landscape); + pt = new PrintJapaneseText(name, font, rotTx, true, preferredSize); + pane.addTab(name, pt); + book.append(pt, portrait); + book.append(pt, landscape); } pjob.setPageable(book); - JFrame f = new JFrame(); - f.add(BorderLayout.CENTER, p); - f.addWindowListener(new WindowAdapter() { - public void windowClosing(WindowEvent e) {System.exit(0);} + JButton printButton = new JButton("Print"); + printButton.addActionListener(event -> { + try { + if (pjob.printDialog()) { + pjob.print(); + } + } catch (PrinterException e) { + throw new RuntimeException(e.getMessage(), e); + } }); + + JFrame f = new JFrame("PrintTextTest"); + f.add(BorderLayout.CENTER, pane); + f.add(BorderLayout.SOUTH, printButton); f.pack(); - f.show(); - try { - if (pjob.printDialog()) { - pjob.print(); - } - } catch (PrinterException e) { - throw new RuntimeException(e.getMessage()); - } + PassFailJFrame.builder() + .title("PrintTextTest") + .instructions(INSTRUCTIONS) + .testTimeOut(10) + .columns(60) + .testUI(f) + .build() + .awaitAndCheck(); } // The test needs a physical font that supports Latin. @@ -221,338 +235,228 @@ private static Font getPhysicalFont() { String[] names = ge.getAvailableFontFamilyNames(); for (String n : names) { - switch (n.toLowerCase()) { - case "dialog": - case "dialoginput": - case "serif": - case "sansserif": - case "monospaced": - break; + switch (n) { + case Font.DIALOG: + case Font.DIALOG_INPUT: + case Font.SERIF: + case Font.SANS_SERIF: + case Font.MONOSPACED: + continue; default: Font f = new Font(n, Font.PLAIN, 18); if (f.canDisplayUpTo("AZaz09") == -1) { physicalFont = f; return f; } - } + } } physicalFont = new Font(Font.DIALOG, Font.PLAIN, 18); return physicalFont; } - public PrintTextTest(String page, Font font, AffineTransform gxTx, - boolean fm) { - this.page = page; - textFont = font; - this.gxTx = gxTx; - this.useFM = fm; - setBackground(Color.white); - } - - public static AttributedCharacterIterator getIterator(String s) { - return new AttributedString(s).getIterator(); - } - - static String orient(PageFormat pf) { - if (pf.getOrientation() == PageFormat.PORTRAIT) { - return "Portrait"; - } else { - return "Landscape"; + private static class PrintText extends Component implements Printable { + + protected final Font textFont; + protected final AffineTransform gxTx; + protected final String page; + protected final boolean useFM; + protected final int preferredSize; + + public PrintText(String page, Font font, AffineTransform gxTx, boolean fm, int size) { + this.page = page; + this.textFont = font; + this.gxTx = gxTx; + this.useFM = fm; + this.preferredSize = size; + setBackground(Color.WHITE); } - } - public int print(Graphics g, PageFormat pf, int pageIndex) { - - Graphics2D g2d = (Graphics2D)g; - g2d.translate(pf.getImageableX(), pf.getImageableY()); - g.drawString(page+" "+orient(pf),50,20); - g.translate(0, 25); - paint(g); - return PAGE_EXISTS; - } - - public Dimension getMinimumSize() { - return getPreferredSize(); - } - - public Dimension getPreferredSize() { - return new Dimension(preferredSize, preferredSize); - } - - public void paint(Graphics g) { - - /* fill with white before any transformation is applied */ - g.setColor(Color.white); - g.fillRect(0, 0, getSize().width, getSize().height); - - - Graphics2D g2d = (Graphics2D) g; - if (gxTx != null) { - g2d.transform(gxTx); + private static AttributedCharacterIterator getIterator(String s) { + return new AttributedString(s).getIterator(); } - if (useFM) { - g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, - RenderingHints.VALUE_FRACTIONALMETRICS_ON); - } - - g.setFont(textFont); - FontMetrics fm = g.getFontMetrics(); - String s; - int LS = 30; - int ix=10, iy=LS+10; - g.setColor(Color.black); - - s = "drawString(String str, int x, int y)"; - g.drawString(s, ix, iy); - if (!textFont.isTransformed()) { - g.drawLine(ix, iy+1, ix+fm.stringWidth(s), iy+1); + private static String orient(PageFormat pf) { + if (pf.getOrientation() == PageFormat.PORTRAIT) { + return "Portrait"; + } else { + return "Landscape"; + } } - iy += LS; - s = "drawString(AttributedCharacterIterator iterator, int x, int y)"; - g.drawString(getIterator(s), ix, iy); - - iy += LS; - s = "\tdrawChars(\t\r\nchar[], int off, int len, int x, int y\t)"; - g.drawChars(s.toCharArray(), 0, s.length(), ix, iy); - if (!textFont.isTransformed()) { - g.drawLine(ix, iy+1, ix+fm.stringWidth(s), iy+1); + @Override + public int print(Graphics g, PageFormat pf, int pageIndex) { + Graphics2D g2d = (Graphics2D) g; + g2d.translate(pf.getImageableX(), pf.getImageableY()); + g.drawString(page + " " + orient(pf), 50, 20); + g.translate(0, 25); + paint(g); + return PAGE_EXISTS; } - iy += LS; - s = "drawBytes(byte[], int off, int len, int x, int y)"; - byte data[] = new byte[s.length()]; - for (int i = 0; i < data.length; i++) { - data[i] = (byte) s.charAt(i); + @Override + public Dimension getMinimumSize() { + return getPreferredSize(); } - g.drawBytes(data, 0, data.length, ix, iy); - Font f = g2d.getFont(); - FontRenderContext frc = g2d.getFontRenderContext(); - - iy += LS; - s = "drawString(String s, float x, float y)"; - g2d.drawString(s, (float) ix, (float) iy); - if (!textFont.isTransformed()) { - g.drawLine(ix, iy+1, ix+fm.stringWidth(s), iy+1); + @Override + public Dimension getPreferredSize() { + return new Dimension(preferredSize, preferredSize); } - iy += LS; - s = "drawString(AttributedCharacterIterator iterator, "+ - "float x, float y)"; - g2d.drawString(getIterator(s), (float) ix, (float) iy); - - iy += LS; - s = "drawGlyphVector(GlyphVector g, float x, float y)"; - GlyphVector gv = f.createGlyphVector(frc, s); - g2d.drawGlyphVector(gv, ix, iy); - Point2D adv = gv.getGlyphPosition(gv.getNumGlyphs()); - if (!textFont.isTransformed()) { - g.drawLine(ix, iy+1, ix+(int)adv.getX(), iy+1); - } + @Override + public void paint(Graphics g) { - iy += LS; - s = "GlyphVector with position adjustments"; - - gv = f.createGlyphVector(frc, s); - int ng = gv.getNumGlyphs(); - adv = gv.getGlyphPosition(ng); - for (int i=0; i(), frc); + tl.draw(g2d, ix, iy); - String text = TEXT + TEXT + TEXT; - g.setColor(Color.black); - int y = 20; - float origSize = 7f; - for (int i=0;i<11;i++) { - float size = origSize+(i*0.1f); - g2d.translate(0, size+6); - Font f = textFont.deriveFont(size); - g2d.setFont(f); - FontMetrics fontMetrics = g2d.getFontMetrics(); - int stringWidth = fontMetrics.stringWidth(text); - g.drawLine(0, y+1, stringWidth, y+1); - g.drawString(text, 0, y); - y +=10; + iy += LS; + s = "TextLayout 2: \u0924\u094d\u0930 \u0915\u0948\u0930\u0947 End."; + tl = new TextLayout(s, f, frc); + tl.draw(g2d, ix, iy); } } -} - -class Sysout - { - private static TestDialog dialog; - public static void createDialogWithInstructions( String[] instructions ) - { - dialog = new TestDialog( new Frame(), "Instructions" ); - dialog.printInstructions( instructions ); - dialog.show(); - println( "Any messages for the tester will display here." ); - } + private static class PrintJapaneseText extends PrintText { - public static void createDialog( ) - { - dialog = new TestDialog( new Frame(), "Instructions" ); - String[] defInstr = { "Instructions will appear here. ", "" } ; - dialog.printInstructions( defInstr ); - dialog.show(); - println( "Any messages for the tester will display here." ); - } + public PrintJapaneseText(String page, Font font, AffineTransform gxTx, boolean fm, int size) { + super(page, font, gxTx, fm, size); + } + private static final String TEXT = + "\u3042\u3044\u3046\u3048\u304a\u30a4\u30ed\u30cf" + + "\u30cb\u30db\u30d8\u30c8\u4e00\u4e01\u4e02\u4e05\uff08"; - public static void printInstructions( String[] instructions ) - { - dialog.printInstructions( instructions ); - } + @Override + public void paint(Graphics g) { + g.setColor(Color.WHITE); + g.fillRect(0, 0, getSize().width, getSize().height); - public static void println( String messageIn ) - { - dialog.displayMessage( messageIn ); - } + Graphics2D g2d = (Graphics2D) g; + if (gxTx != null) { + g2d.transform(gxTx); + } + if (useFM) { + g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, + RenderingHints.VALUE_FRACTIONALMETRICS_ON); + } - }// Sysout class - -/** - This is part of the standard test machinery. It provides a place for the - test instructions to be displayed, and a place for interactive messages - to the user to be displayed. - To have the test instructions displayed, see Sysout. - To have a message to the user be displayed, see Sysout. - Do not call anything in this dialog directly. - */ -class TestDialog extends Dialog - { - - TextArea instructionsText; - TextArea messageText; - int maxStringLength = 80; - - //DO NOT call this directly, go through Sysout - public TestDialog( Frame frame, String name ) - { - super( frame, name ); - int scrollBoth = TextArea.SCROLLBARS_BOTH; - instructionsText = new TextArea( "", 20, maxStringLength, scrollBoth ); - add( "North", instructionsText ); - - messageText = new TextArea( "", 5, maxStringLength, scrollBoth ); - add("South", messageText); - - pack(); - - show(); - }// TestDialog() - - //DO NOT call this directly, go through Sysout - public void printInstructions( String[] instructions ) - { - //Clear out any current instructions - instructionsText.setText( "" ); - - //Go down array of instruction strings - - String printStr, remainingStr; - for( int i=0; i < instructions.length; i++ ) - { - //chop up each into pieces maxSringLength long - remainingStr = instructions[ i ]; - while( remainingStr.length() > 0 ) - { - //if longer than max then chop off first max chars to print - if( remainingStr.length() >= maxStringLength ) - { - //Try to chop on a word boundary - int posOfSpace = remainingStr. - lastIndexOf( ' ', maxStringLength - 1 ); - - if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1; - - printStr = remainingStr.substring( 0, posOfSpace + 1 ); - remainingStr = remainingStr.substring( posOfSpace + 1 ); - } - //else just print - else - { - printStr = remainingStr; - remainingStr = ""; - } - - instructionsText.append( printStr + "\n" ); - - }// while - - }// for - - }//printInstructions() - - //DO NOT call this directly, go through Sysout - public void displayMessage( String messageIn ) - { - messageText.append( messageIn + "\n" ); + String text = TEXT + TEXT + TEXT; + g.setColor(Color.BLACK); + int y = 20; + float origSize = 7f; + for (int i = 0; i < 11; i++) { + float size = origSize + (i * 0.1f); + g2d.translate(0, size + 6); + Font f = textFont.deriveFont(size); + g2d.setFont(f); + FontMetrics fontMetrics = g2d.getFontMetrics(); + int stringWidth = fontMetrics.stringWidth(text); + g.drawLine(0, y + 1, stringWidth, y + 1); + g.drawString(text, 0, y); + y += 10; + } + } } - -}// TestDialog class +} diff --git a/test/jdk/java/foreign/TestMemorySession.java b/test/jdk/java/foreign/TestMemorySession.java index 617951f6b6b1e..e5b4ca74027f1 100644 --- a/test/jdk/java/foreign/TestMemorySession.java +++ b/test/jdk/java/foreign/TestMemorySession.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -28,12 +28,6 @@ */ import java.lang.foreign.Arena; - -import jdk.internal.foreign.MemorySessionImpl; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; -import static org.testng.Assert.*; - import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; @@ -41,6 +35,11 @@ import java.util.concurrent.atomic.AtomicReference; import java.util.function.Supplier; import java.util.stream.IntStream; +import jdk.internal.foreign.MemorySessionImpl; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import static org.testng.Assert.*; public class TestMemorySession { @@ -319,6 +318,70 @@ public void testIsCloseableBy(ArenaSupplier arenaSupplier) { assertEquals(sessionImpl.isCloseableBy(otherThread), isCloseableByOther); } + /** + * Test that a thread failing to acquire a scope will not observe it as alive afterwards. + */ + @Test + public void testAcquireCloseRace() throws InterruptedException { + int iteration = 1000; + AtomicInteger lock = new AtomicInteger(); + boolean[] result = new boolean[1]; + lock.set(-2); + MemorySessionImpl[] scopes = new MemorySessionImpl[iteration]; + for (int i = 0; i < iteration; i++) { + scopes[i] = MemorySessionImpl.toMemorySession(Arena.ofShared()); + } + + // This thread tries to close the scopes + Thread t1 = new Thread(() -> { + for (int i = 0; i < iteration; i++) { + MemorySessionImpl scope = scopes[i]; + while (true) { + try { + scope.close(); + break; + } catch (IllegalStateException e) {} + } + // Keep the 2 threads operating on the same scope + int k = lock.getAndAdd(1) + 1; + while (k != i * 2) { + Thread.onSpinWait(); + k = lock.get(); + } + } + }); + + // This thread tries to acquire the scopes, then check if it is alive after an acquire failure + Thread t2 = new Thread(() -> { + for (int i = 0; i < iteration; i++) { + MemorySessionImpl scope = scopes[i]; + while (true) { + try { + scope.acquire0(); + } catch (IllegalStateException e) { + if (scope.isAlive()) { + result[0] = true; + } + break; + } + scope.release0(); + } + // Keep the 2 threads operating on the same scope + int k = lock.getAndAdd(1) + 1; + while (k != i * 2) { + Thread.onSpinWait(); + k = lock.get(); + } + } + }); + + t1.start(); + t2.start(); + t1.join(); + t2.join(); + assertFalse(result[0]); + } + private void waitSomeTime() { try { Thread.sleep(10); diff --git a/test/jdk/java/nio/file/attribute/BasicFileAttributeView/SetTimesNanos.java b/test/jdk/java/nio/file/attribute/BasicFileAttributeView/SetTimesNanos.java index 0c07c9ab9db90..d71b9407bbce3 100644 --- a/test/jdk/java/nio/file/attribute/BasicFileAttributeView/SetTimesNanos.java +++ b/test/jdk/java/nio/file/attribute/BasicFileAttributeView/SetTimesNanos.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 @@ -22,10 +22,13 @@ */ /* @test - * @bug 8181493 8231174 + * @bug 8181493 8231174 8343417 * @summary Verify that nanosecond precision is maintained for file timestamps * @requires (os.family == "linux") | (os.family == "mac") | (os.family == "windows") + * @library ../.. /test/lib + * @build jdk.test.lib.Platform * @modules java.base/sun.nio.fs:+open + * @run main SetTimesNanos */ import java.io.IOException; @@ -36,15 +39,19 @@ import java.nio.file.attribute.BasicFileAttributes; import java.nio.file.attribute.BasicFileAttributeView; import java.nio.file.attribute.FileTime; +import java.util.List; import java.util.Set; -import java.util.concurrent.TimeUnit; + +import static java.nio.file.LinkOption.*; +import static java.util.concurrent.TimeUnit.*; + +import jdk.test.lib.Platform; +import jtreg.SkippedException; public class SetTimesNanos { - private static final boolean IS_WINDOWS = - System.getProperty("os.name").startsWith("Windows"); public static void main(String[] args) throws Exception { - if (!IS_WINDOWS) { + if (!Platform.isWindows()) { // Check whether futimens() system call is supported Class unixNativeDispatcherClass = Class.forName("sun.nio.fs.UnixNativeDispatcher"); @@ -52,8 +59,7 @@ public static void main(String[] args) throws Exception { unixNativeDispatcherClass.getDeclaredMethod("futimensSupported"); futimensSupported.setAccessible(true); if (!(boolean)futimensSupported.invoke(null)) { - System.err.println("futimens() not supported; skipping test"); - return; + throw new SkippedException("futimens() not supported"); } } @@ -63,30 +69,34 @@ public static void main(String[] args) throws Exception { System.out.format("FileStore: \"%s\" on %s (%s)%n", dir, store.name(), store.type()); - Set testedTypes = IS_WINDOWS ? + Set testedTypes = Platform.isWindows() ? Set.of("NTFS") : Set.of("apfs", "ext4", "xfs", "zfs"); if (!testedTypes.contains(store.type())) { - System.err.format("%s not in %s; skipping test", store.type(), testedTypes); - return; + throw new SkippedException(store.type() + " not in " + testedTypes); } testNanos(dir); Path file = Files.createFile(dir.resolve("test.dat")); testNanos(file); + + if (Platform.isLinux()) { + testNanosLink(false); + testNanosLink(true); + } } private static void testNanos(Path path) throws IOException { // Set modification and access times // Time stamp = "2017-01-01 01:01:01.123456789"; long timeNanos = 1_483_261_261L*1_000_000_000L + 123_456_789L; - FileTime pathTime = FileTime.from(timeNanos, TimeUnit.NANOSECONDS); + FileTime pathTime = FileTime.from(timeNanos, NANOSECONDS); BasicFileAttributeView view = Files.getFileAttributeView(path, BasicFileAttributeView.class); view.setTimes(pathTime, pathTime, null); // Windows file time resolution is 100ns so truncate - if (IS_WINDOWS) { + if (Platform.isWindows()) { timeNanos = 100L*(timeNanos/100L); } @@ -99,7 +109,7 @@ private static void testNanos(Path path) throws IOException { FileTime[] times = new FileTime[] {attrs.lastModifiedTime(), attrs.lastAccessTime()}; for (int i = 0; i < timeNames.length; i++) { - long nanos = times[i].to(TimeUnit.NANOSECONDS); + long nanos = times[i].to(NANOSECONDS); if (nanos != timeNanos) { throw new RuntimeException("Expected " + timeNames[i] + " timestamp to be '" + timeNanos + "', but was '" + @@ -107,4 +117,42 @@ private static void testNanos(Path path) throws IOException { } } } + + private static void testNanosLink(boolean absolute) throws IOException { + System.out.println("absolute: " + absolute); + + var target = Path.of("target"); + var symlink = Path.of("symlink"); + if (absolute) + symlink = symlink.toAbsolutePath(); + + try { + Files.createFile(target); + Files.createSymbolicLink(symlink, target); + + var newTime = FileTime.from(1730417633157646106L, NANOSECONDS); + System.out.println("newTime: " + newTime.to(NANOSECONDS)); + + for (Path p : List.of(target, symlink)) { + System.out.println("p: " + p); + + var view = Files.getFileAttributeView(p, + BasicFileAttributeView.class, NOFOLLOW_LINKS); + view.setTimes(newTime, newTime, null); + var attrs = view.readAttributes(); + + if (!attrs.lastAccessTime().equals(newTime)) + throw new RuntimeException("Last access time " + + attrs.lastAccessTime() + + " != " + newTime); + if (!attrs.lastAccessTime().equals(newTime)) + throw new RuntimeException("Last modified time " + + attrs.lastModifiedTime() + + " != " + newTime); + } + } finally { + Files.deleteIfExists(target); + Files.deleteIfExists(symlink); + } + } } diff --git a/test/jdk/javax/management/remote/mandatory/connection/DeadLockTest.java b/test/jdk/javax/management/remote/mandatory/connection/DeadLockTest.java index 0526f86b4a1f1..677341aacb16c 100644 --- a/test/jdk/javax/management/remote/mandatory/connection/DeadLockTest.java +++ b/test/jdk/javax/management/remote/mandatory/connection/DeadLockTest.java @@ -27,6 +27,10 @@ * @summary test on a client notification deadlock. * @author Shanliang JIANG * + * @requires vm.compMode != "Xcomp" + * @comment Running with -Xcomp is likely to cause a timeout while establishing the connection + * (RMI: java.rmi.NoSuchObjectException: no such object in table). + * * @run clean DeadLockTest * @run build DeadLockTest * @run main DeadLockTest @@ -139,7 +143,7 @@ public void handleNotification(Notification n, Object h) { try { conn.getDefaultDomain(); } catch (IOException ioe) { - // Greate ! + // OK } synchronized(this) { diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java index e332480e35ae4..02841a1a71337 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java @@ -61,6 +61,7 @@ import java.util.stream.Collectors; import static java.util.stream.Collectors.toSet; import java.util.stream.Stream; +import jdk.internal.util.OperatingSystem; import jdk.jpackage.test.Functional.ExceptionBox; import jdk.jpackage.test.Functional.ThrowingConsumer; import jdk.jpackage.test.Functional.ThrowingRunnable; @@ -68,8 +69,6 @@ public final class TKit { - private static final String OS = System.getProperty("os.name").toLowerCase(); - public static final Path TEST_SRC_ROOT = Functional.identity(() -> { Path root = Path.of(System.getProperty("test.src")); @@ -176,15 +175,15 @@ static String getCurrentDefaultAppName() { } public static boolean isWindows() { - return (OS.contains("win")); + return OperatingSystem.isWindows(); } public static boolean isOSX() { - return (OS.contains("mac")); + return OperatingSystem.isMacOS(); } public static boolean isLinux() { - return ((OS.contains("nix") || OS.contains("nux"))); + return OperatingSystem.isLinux(); } public static boolean isLinuxAPT() { diff --git a/test/jdk/tools/jpackage/macosx/HostArchPkgTest.java b/test/jdk/tools/jpackage/macosx/HostArchPkgTest.java index 5829aba23cc11..69e1cd6c42a9e 100644 --- a/test/jdk/tools/jpackage/macosx/HostArchPkgTest.java +++ b/test/jdk/tools/jpackage/macosx/HostArchPkgTest.java @@ -28,6 +28,7 @@ import javax.xml.xpath.XPath; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathFactory; +import jdk.internal.util.Architecture; import jdk.jpackage.test.JPackageCommand; import jdk.jpackage.test.PackageTest; import jdk.jpackage.test.PackageType; @@ -73,7 +74,7 @@ private static void verifyHostArch(JPackageCommand cmd) throws Exception { "/installer-gui-script/options/@hostArchitectures", doc, XPathConstants.STRING); - if ("aarch64".equals(System.getProperty("os.arch"))) { + if (Architecture.isAARCH64()) { TKit.assertEquals(v, "arm64", "Check value of \"hostArchitectures\" attribute"); } else { diff --git a/test/jdk/tools/sincechecker/TEST.properties b/test/jdk/tools/sincechecker/TEST.properties new file mode 100644 index 0000000000000..27f669ef4cafe --- /dev/null +++ b/test/jdk/tools/sincechecker/TEST.properties @@ -0,0 +1,4 @@ +modules = \ + jdk.compiler/com.sun.tools.javac.api \ + jdk.compiler/com.sun.tools.javac.util \ + jdk.compiler/com.sun.tools.javac.code diff --git a/test/jdk/tools/sincechecker/modules/java_base/CheckSince_javaBase.java b/test/jdk/tools/sincechecker/modules/java.base/JavaBaseCheckSince.java similarity index 81% rename from test/jdk/tools/sincechecker/modules/java_base/CheckSince_javaBase.java rename to test/jdk/tools/sincechecker/modules/java.base/JavaBaseCheckSince.java index 6d0b9d0e932e8..64d5bf2465f60 100644 --- a/test/jdk/tools/sincechecker/modules/java_base/CheckSince_javaBase.java +++ b/test/jdk/tools/sincechecker/modules/java.base/JavaBaseCheckSince.java @@ -24,11 +24,7 @@ /* * @test * @bug 8331051 - * @summary Test for `@since` for java.base module - * @library /test/lib - * /test/jdk/tools/sincechecker - * @modules jdk.compiler/com.sun.tools.javac.api - * jdk.compiler/com.sun.tools.javac.util - * jdk.compiler/com.sun.tools.javac.code + * @summary Test for `@since` in java.base module + * @library /test/lib /test/jdk/tools/sincechecker * @run main SinceChecker java.base --exclude java.lang.classfile */ diff --git a/test/jdk/tools/sincechecker/modules/java.compiler/JavaCompilerCheckSince.java b/test/jdk/tools/sincechecker/modules/java.compiler/JavaCompilerCheckSince.java new file mode 100644 index 0000000000000..c843c962d2787 --- /dev/null +++ b/test/jdk/tools/sincechecker/modules/java.compiler/JavaCompilerCheckSince.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8341399 + * @summary Test for `@since` in java.compiler module + * @library /test/lib /test/jdk/tools/sincechecker + * @run main SinceChecker java.compiler + */ diff --git a/test/jdk/tools/sincechecker/modules/jdk.compiler/JdkCompilerCheckSince.java b/test/jdk/tools/sincechecker/modules/jdk.compiler/JdkCompilerCheckSince.java new file mode 100644 index 0000000000000..5eb819786e925 --- /dev/null +++ b/test/jdk/tools/sincechecker/modules/jdk.compiler/JdkCompilerCheckSince.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8341399 + * @summary Test for `@since` in jdk.compiler module + * @library /test/lib /test/jdk/tools/sincechecker + * @run main SinceChecker jdk.compiler + */ diff --git a/test/jdk/tools/sincechecker/modules/jdk.javadoc/JdkJavadocCheckSince.java b/test/jdk/tools/sincechecker/modules/jdk.javadoc/JdkJavadocCheckSince.java new file mode 100644 index 0000000000000..0e68d8213e965 --- /dev/null +++ b/test/jdk/tools/sincechecker/modules/jdk.javadoc/JdkJavadocCheckSince.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8341399 + * @summary Test for `@since` in jdk.javadoc module + * @library /test/lib /test/jdk/tools/sincechecker + * @run main SinceChecker jdk.javadoc + */ diff --git a/test/jdk/tools/sincechecker/modules/jdk.jdeps/JdkJdepsCheckSince.java b/test/jdk/tools/sincechecker/modules/jdk.jdeps/JdkJdepsCheckSince.java new file mode 100644 index 0000000000000..68439c49e2483 --- /dev/null +++ b/test/jdk/tools/sincechecker/modules/jdk.jdeps/JdkJdepsCheckSince.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8341399 + * @summary Test for `@since` in jdk.jdeps module + * @library /test/lib /test/jdk/tools/sincechecker + * @run main SinceChecker jdk.jdeps + */ diff --git a/test/jdk/tools/sincechecker/modules/jdk.jshell/JdkJshellCheckSince.java b/test/jdk/tools/sincechecker/modules/jdk.jshell/JdkJshellCheckSince.java new file mode 100644 index 0000000000000..09f762cfebab1 --- /dev/null +++ b/test/jdk/tools/sincechecker/modules/jdk.jshell/JdkJshellCheckSince.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8341399 + * @summary Test for `@since` in jdk.jshell module + * @library /test/lib /test/jdk/tools/sincechecker + * @run main SinceChecker jdk.jshell + */ diff --git a/test/langtools/tools/javac/sealed/SealedCompilationTests.java b/test/langtools/tools/javac/sealed/SealedCompilationTests.java index 5ad70d102d667..dee64fd0865aa 100644 --- a/test/langtools/tools/javac/sealed/SealedCompilationTests.java +++ b/test/langtools/tools/javac/sealed/SealedCompilationTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 @@ -1178,6 +1178,39 @@ void test () { I[] i = (I[]) c; } } + """, + """ + class Test { + sealed interface I permits C1 {} + non-sealed class C1 implements I {} + class C2 extends C1 {} + class C3 {} + I m(int s, C3 c3) { + I i = (I)c3; + } + } + """, + """ + class Test { + sealed interface I permits C1 {} + non-sealed class C1 implements I {} + class C2 extends C1 {} + class C3 {} + I m(int s, C3 c3) { + I i = (C1)c3; + } + } + """, + """ + class Test { + sealed interface I permits C1 {} + non-sealed class C1 implements I {} + class C2 extends C1 {} + class C3 {} + I m(int s, C3 c3) { + I i = (C2)c3; + } + } """ )) { assertFail("compiler.err.prob.found.req", s); diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/AllocFromTest.java b/test/micro/org/openjdk/bench/java/lang/foreign/AllocFromTest.java index 520c1ad5a9bc4..b627c4de08954 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/AllocFromTest.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/AllocFromTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 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 @@ -48,7 +48,7 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.NANOSECONDS) -@Fork(value = 3, jvmArgs = { "--enable-native-access=ALL-UNNAMED" }) +@Fork(value = 3, jvmArgs = { "--enable-native-access=ALL-UNNAMED", "--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED" }) public class AllocFromTest extends CLayouts { Arena arena = Arena.ofConfined(); diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/AllocTest.java b/test/micro/org/openjdk/bench/java/lang/foreign/AllocTest.java index d9b268a1846a2..a70861a0dda7e 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/AllocTest.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/AllocTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 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 @@ -50,7 +50,7 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.NANOSECONDS) -@Fork(value = 3, jvmArgs = { "--enable-native-access=ALL-UNNAMED" }) +@Fork(value = 3, jvmArgs = { "--enable-native-access=ALL-UNNAMED", "--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED" }) public class AllocTest extends CLayouts { Arena arena = Arena.ofConfined(); diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/BulkOps.java b/test/micro/org/openjdk/bench/java/lang/foreign/BulkOps.java index f779d52151c55..6a1dd05b615e5 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/BulkOps.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/BulkOps.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -51,7 +51,7 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.MILLISECONDS) -@Fork(3) +@Fork(value = 3, jvmArgs = { "--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED" }) public class BulkOps { static final Unsafe unsafe = Utils.unsafe; diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverConstant.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverConstant.java index 8f758477cbee2..a725b427038d1 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverConstant.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverConstant.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -48,7 +48,7 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.MILLISECONDS) -@Fork(3) +@Fork(value = 3, jvmArgs = { "--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED" }) public class LoopOverConstant extends JavaLayouts { static final Unsafe unsafe = Utils.unsafe; diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNew.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNew.java index d74ac8fbceea5..c0d16f9818d97 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNew.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNew.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -47,7 +47,7 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.MILLISECONDS) -@Fork(3) +@Fork(value = 3, jvmArgs = { "--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED" }) public class LoopOverNew extends JavaLayouts { static final Unsafe unsafe = Utils.unsafe; diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNewHeap.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNewHeap.java index 94c220292a004..e869a92c4d807 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNewHeap.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNewHeap.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -47,7 +47,7 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.MILLISECONDS) -@Fork(3) +@Fork(value = 3, jvmArgs = { "--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED" }) public class LoopOverNewHeap extends JavaLayouts { static final Unsafe unsafe = Utils.unsafe; diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstant.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstant.java index da7d15483e869..668a6ab8e3044 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstant.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstant.java @@ -51,7 +51,7 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.MILLISECONDS) -@Fork(3) +@Fork(value = 3, jvmArgs = { "--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED" }) public class LoopOverNonConstant extends JavaLayouts { static final Unsafe unsafe = Utils.unsafe; diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantAsType.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantAsType.java index 547e3bc298f97..e7c08512db371 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantAsType.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantAsType.java @@ -54,7 +54,7 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.MILLISECONDS) -@Fork(value = 3, jvmArgs = { "-XX:-TieredCompilation" }) +@Fork(value = 3, jvmArgs = { "-XX:-TieredCompilation", "--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED" }) public class LoopOverNonConstantAsType extends JavaLayouts { static final Unsafe unsafe = Utils.unsafe; diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantFP.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantFP.java index 4a24512b22dc4..7bc39f5e3724d 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantFP.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantFP.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -48,7 +48,7 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.MILLISECONDS) -@Fork(3) +@Fork(value = 3, jvmArgs = {"--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED" }) public class LoopOverNonConstantFP { static final Unsafe unsafe = Utils.unsafe; diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantHeap.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantHeap.java index e123e5baf1a90..baaa19097188b 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantHeap.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantHeap.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -49,7 +49,7 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.MILLISECONDS) -@Fork(3) +@Fork(value = 3, jvmArgs = { "--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED" }) public class LoopOverNonConstantHeap extends JavaLayouts { static final Unsafe unsafe = Utils.unsafe; diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantMapped.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantMapped.java index ee4a4f3c60bcd..409b837ee8b1b 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantMapped.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantMapped.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -55,7 +55,7 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.MILLISECONDS) -@Fork(3) +@Fork(value = 3, jvmArgs = { "--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED" }) public class LoopOverNonConstantMapped extends JavaLayouts { static final Unsafe unsafe = Utils.unsafe; diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantShared.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantShared.java index 9504439bda111..2c1a5672749e5 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantShared.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantShared.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -48,7 +48,7 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.MILLISECONDS) -@Fork(3) +@Fork(value = 3, jvmArgs = { "--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED" }) public class LoopOverNonConstantShared extends JavaLayouts { static final Unsafe unsafe = Utils.unsafe; diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverPollutedBuffer.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverPollutedBuffer.java index 99cf83b75e5d5..c9060adc18b4b 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverPollutedBuffer.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverPollutedBuffer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -47,7 +47,7 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.MILLISECONDS) -@Fork(3) +@Fork(value = 3, jvmArgs = { "--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED" }) public class LoopOverPollutedBuffer { static final int ELEM_SIZE = 1_000_000; diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverPollutedSegments.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverPollutedSegments.java index 4ad60297a3298..b0fddeeb8da66 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverPollutedSegments.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverPollutedSegments.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -46,7 +46,7 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.MILLISECONDS) -@Fork(3) +@Fork(value = 3, jvmArgs = { "--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED" }) public class LoopOverPollutedSegments extends JavaLayouts { static final int ELEM_SIZE = 1_000_000; diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverRandom.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverRandom.java new file mode 100644 index 0000000000000..392ac6d667ba3 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverRandom.java @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang.foreign; + +import java.lang.foreign.Arena; +import java.lang.foreign.MemorySegment; +import java.lang.foreign.ValueLayout; +import java.util.Random; +import java.util.concurrent.TimeUnit; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.TearDown; +import jdk.internal.misc.Unsafe; + +@BenchmarkMode(Mode.AverageTime) +@Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS) +@Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) +@State(org.openjdk.jmh.annotations.Scope.Thread) +@OutputTimeUnit(TimeUnit.MICROSECONDS) +@Fork(value = 3, jvmArgsAppend = { "--enable-native-access=ALL-UNNAMED", "--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED"}) +public class LoopOverRandom extends JavaLayouts { + static final int SEED = 0; + + static final long ELEM_SIZE = ValueLayout.JAVA_INT.byteSize(); + static final int ELEM_COUNT = 1_000; + static final long ALLOC_SIZE = ELEM_COUNT * ELEM_SIZE; + + static final Unsafe unsafe = Utils.unsafe; + + Arena arena; + MemorySegment segment; + int[] indices; + + static final MemorySegment ALL = MemorySegment.NULL.reinterpret(Long.MAX_VALUE); + + @Setup + public void setup() { + indices = new Random(SEED).ints(0, ELEM_COUNT).limit(ELEM_COUNT).toArray(); + arena = Arena.ofConfined(); + segment = arena.allocate(ALLOC_SIZE); + for (int i = 0; i < ELEM_COUNT; i++) { + segment.setAtIndex(ValueLayout.JAVA_INT, i, i); + } + } + + @TearDown + public void tearDown() { + arena.close(); + } + + @Benchmark + public long segment_loop() { + int sum = 0; + for (int i = 0; i < ELEM_COUNT; i++) { + sum += segment.getAtIndex(ValueLayout.JAVA_INT_UNALIGNED, indices[i]); + target_dontInline(); + } + return sum; + } + + @Benchmark + public long segment_loop_all() { + int sum = 0; + for (int i = 0; i < ELEM_COUNT; i++) { + sum += ALL.get(ValueLayout.JAVA_INT_UNALIGNED, segment.address() + indices[i] * ELEM_SIZE); + target_dontInline(); + } + return sum; + } + + @Benchmark + public long segment_loop_asUnchecked() { + int sum = 0; + for (int i = 0; i < ELEM_COUNT; i++) { + sum += asUnchecked(segment).getAtIndex(ValueLayout.JAVA_INT_UNALIGNED, indices[i]); + target_dontInline(); + } + return sum; + } + + @Benchmark + public long unsafe_loop() { + int sum = 0; + for (int i = 0; i < ELEM_COUNT; i++) { + sum += unsafe.getInt(segment.address() + indices[i] * ELEM_SIZE); + target_dontInline(); + } + return sum; + } + + MemorySegment asUnchecked(MemorySegment segment) { + return MemorySegment.ofAddress(segment.address()).reinterpret(Long.MAX_VALUE); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void target_dontInline() { + // this method was intentionally left blank + } +} diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/MemorySegmentCopyUnsafe.java b/test/micro/org/openjdk/bench/java/lang/foreign/MemorySegmentCopyUnsafe.java index ffdff6e64efaa..a0b57b5662c87 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/MemorySegmentCopyUnsafe.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/MemorySegmentCopyUnsafe.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,7 +45,7 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.NANOSECONDS) -@Fork(value = 3, jvmArgs = {"--enable-native-access=ALL-UNNAMED"}) +@Fork(value = 3, jvmArgs = {"--enable-native-access=ALL-UNNAMED", "--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED"}) public class MemorySegmentCopyUnsafe { static final Unsafe UNSAFE = Utils.unsafe; diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/MemorySegmentGetUnsafe.java b/test/micro/org/openjdk/bench/java/lang/foreign/MemorySegmentGetUnsafe.java index 11cb1e9888949..b18696a14246c 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/MemorySegmentGetUnsafe.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/MemorySegmentGetUnsafe.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 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 @@ -50,7 +50,7 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.NANOSECONDS) -@Fork(value = 3, jvmArgs = {"--enable-native-access=ALL-UNNAMED"}) +@Fork(value = 3, jvmArgs = {"--enable-native-access=ALL-UNNAMED", "--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED"}) public class MemorySegmentGetUnsafe { static final Unsafe UNSAFE = Utils.unsafe; diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/MemorySegmentZeroUnsafe.java b/test/micro/org/openjdk/bench/java/lang/foreign/MemorySegmentZeroUnsafe.java index 72fdded386fd8..09e5a1e3e77cb 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/MemorySegmentZeroUnsafe.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/MemorySegmentZeroUnsafe.java @@ -44,7 +44,7 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.NANOSECONDS) -@Fork(value = 3, jvmArgs = {"--enable-native-access=ALL-UNNAMED"}) +@Fork(value = 3, jvmArgs = {"--enable-native-access=ALL-UNNAMED", "--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED"}) public class MemorySegmentZeroUnsafe { static final Unsafe UNSAFE = Utils.unsafe; diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/ParallelSum.java b/test/micro/org/openjdk/bench/java/lang/foreign/ParallelSum.java index 3d00674f89e85..42c6e481a7239 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/ParallelSum.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/ParallelSum.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -52,7 +52,7 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.MILLISECONDS) -@Fork(3) +@Fork(value = 3, jvmArgs = {"--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED"}) public class ParallelSum extends JavaLayouts { final static int CARRIER_SIZE = 4; diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/UnrolledAccess.java b/test/micro/org/openjdk/bench/java/lang/foreign/UnrolledAccess.java index 197dcf99e287c..a52f91813505e 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/UnrolledAccess.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/UnrolledAccess.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -40,7 +40,7 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.MICROSECONDS) -@Fork(value = 3, jvmArgs = { "--enable-native-access=ALL-UNNAMED" }) +@Fork(value = 3, jvmArgs = {"--enable-native-access=ALL-UNNAMED", "--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED"}) public class UnrolledAccess extends JavaLayouts { static final Unsafe U = Utils.unsafe; diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/xor/GetArrayUnsafeXorOpImpl.java b/test/micro/org/openjdk/bench/java/lang/foreign/xor/GetArrayUnsafeXorOpImpl.java index 9054c0dbd1e92..0b29f925c7c30 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/xor/GetArrayUnsafeXorOpImpl.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/xor/GetArrayUnsafeXorOpImpl.java @@ -1,7 +1,31 @@ +/* + * Copyright (c) 2023, 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. + */ + package org.openjdk.bench.java.lang.foreign.xor; import org.openjdk.bench.java.lang.foreign.Utils; import jdk.internal.misc.Unsafe; +import org.openjdk.jmh.annotations.Fork; import java.lang.foreign.Arena; import java.lang.foreign.FunctionDescriptor; @@ -14,6 +38,7 @@ import static java.lang.foreign.ValueLayout.JAVA_BYTE; import static org.openjdk.bench.java.lang.foreign.CLayouts.*; +@Fork(value = 3, jvmArgs = {"--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED"}) public class GetArrayUnsafeXorOpImpl implements XorOp { static final Unsafe UNSAFE = Utils.unsafe;