diff --git a/src/hotspot/cpu/aarch64/compressedKlass_aarch64.cpp b/src/hotspot/cpu/aarch64/compressedKlass_aarch64.cpp index b96241aab19..6ad6e3134bc 100644 --- a/src/hotspot/cpu/aarch64/compressedKlass_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/compressedKlass_aarch64.cpp @@ -24,12 +24,14 @@ */ #include "precompiled.hpp" -#include "asm/assembler.hpp" +#include "asm/macroAssembler.hpp" #include "logging/log.hpp" #include "oops/compressedKlass.hpp" #include "memory/metaspace.hpp" +#include "runtime/java.hpp" #include "runtime/os.hpp" #include "utilities/globalDefinitions.hpp" +#include "utilities/formatBuffer.hpp" // Helper function; reserve at an address that is compatible with EOR static char* reserve_at_eor_compatible_address(size_t size, bool aslr) { @@ -79,6 +81,7 @@ static char* reserve_at_eor_compatible_address(size_t size, bool aslr) { } return result; } + char* CompressedKlassPointers::reserve_address_space_for_compressed_classes(size_t size, bool aslr, bool optimize_for_zero_base) { char* result = nullptr; @@ -117,3 +120,12 @@ char* CompressedKlassPointers::reserve_address_space_for_compressed_classes(size return result; } + +bool CompressedKlassPointers::check_klass_decode_mode(address base, int shift, const size_t range) { + return MacroAssembler::check_klass_decode_mode(base, shift, range); +} + +bool CompressedKlassPointers::set_klass_decode_mode() { + const size_t range = klass_range_end() - base(); + return MacroAssembler::set_klass_decode_mode(_base, _shift, range); +} diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp index a836d71205e..d561fb912a3 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp @@ -5291,32 +5291,47 @@ void MacroAssembler::decode_heap_oop_not_null(Register dst, Register src) { MacroAssembler::KlassDecodeMode MacroAssembler::_klass_decode_mode(KlassDecodeNone); MacroAssembler::KlassDecodeMode MacroAssembler::klass_decode_mode() { - assert(UseCompressedClassPointers, "not using compressed class pointers"); assert(Metaspace::initialized(), "metaspace not initialized yet"); + assert(_klass_decode_mode != KlassDecodeNone, "should be initialized"); + return _klass_decode_mode; +} - if (_klass_decode_mode != KlassDecodeNone) { - return _klass_decode_mode; - } +MacroAssembler::KlassDecodeMode MacroAssembler::klass_decode_mode(address base, int shift, const size_t range) { + assert(UseCompressedClassPointers, "not using compressed class pointers"); + + // KlassDecodeMode shouldn't be set already. + assert(_klass_decode_mode == KlassDecodeNone, "set once"); - if (CompressedKlassPointers::base() == nullptr) { - return (_klass_decode_mode = KlassDecodeZero); + if (base == nullptr) { + return KlassDecodeZero; } if (operand_valid_for_logical_immediate( - /*is32*/false, (uint64_t)CompressedKlassPointers::base())) { - const size_t range = CompressedKlassPointers::klass_range_end() - CompressedKlassPointers::base(); + /*is32*/false, (uint64_t)base)) { const uint64_t range_mask = right_n_bits(log2i_ceil(range)); - if (((uint64_t)CompressedKlassPointers::base() & range_mask) == 0) { - return (_klass_decode_mode = KlassDecodeXor); + if (((uint64_t)base & range_mask) == 0) { + return KlassDecodeXor; } } const uint64_t shifted_base = - (uint64_t)CompressedKlassPointers::base() >> CompressedKlassPointers::shift(); - guarantee((shifted_base & 0xffff0000ffffffff) == 0, - "compressed class base bad alignment"); + (uint64_t)base >> shift; + if ((shifted_base & 0xffff0000ffffffff) == 0) { + return KlassDecodeMovk; + } + + // No valid encoding. + return KlassDecodeNone; +} + +// Check if one of the above decoding modes will work for given base, shift and range. +bool MacroAssembler::check_klass_decode_mode(address base, int shift, const size_t range) { + return klass_decode_mode(base, shift, range) != KlassDecodeNone; +} - return (_klass_decode_mode = KlassDecodeMovk); +bool MacroAssembler::set_klass_decode_mode(address base, int shift, const size_t range) { + _klass_decode_mode = klass_decode_mode(base, shift, range); + return _klass_decode_mode != KlassDecodeNone; } void MacroAssembler::encode_klass_not_null(Register dst, Register src) { diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp index d9686aec3a9..244de10d0e2 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp @@ -94,11 +94,22 @@ class MacroAssembler: public Assembler { KlassDecodeMovk }; - KlassDecodeMode klass_decode_mode(); + // Calculate decoding mode based on given parameters, used for checking then ultimately setting. + static KlassDecodeMode klass_decode_mode(address base, int shift, const size_t range); private: static KlassDecodeMode _klass_decode_mode; + // Returns above setting with asserts + static KlassDecodeMode klass_decode_mode(); + + public: + // Checks the decode mode and returns false if not compatible with preferred decoding mode. + static bool check_klass_decode_mode(address base, int shift, const size_t range); + + // Sets the decode mode and returns false if cannot be set. + static bool set_klass_decode_mode(address base, int shift, const size_t range); + public: MacroAssembler(CodeBuffer* code) : Assembler(code) {} diff --git a/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp b/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp index 2e062cab605..ef4b39b7c88 100644 --- a/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp +++ b/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp @@ -189,7 +189,7 @@ address TemplateInterpreterGenerator::generate_math_entry(AbstractInterpreter::M } else { fn = CAST_FROM_FN_PTR(address, StubRoutines::dsin()); } - __ call(fn); + __ rt_call(fn); __ mv(ra, x9); break; case Interpreter::java_lang_math_cos : @@ -202,7 +202,7 @@ address TemplateInterpreterGenerator::generate_math_entry(AbstractInterpreter::M } else { fn = CAST_FROM_FN_PTR(address, StubRoutines::dcos()); } - __ call(fn); + __ rt_call(fn); __ mv(ra, x9); break; case Interpreter::java_lang_math_tan : @@ -215,7 +215,7 @@ address TemplateInterpreterGenerator::generate_math_entry(AbstractInterpreter::M } else { fn = CAST_FROM_FN_PTR(address, StubRoutines::dtan()); } - __ call(fn); + __ rt_call(fn); __ mv(ra, x9); break; case Interpreter::java_lang_math_log : @@ -228,7 +228,7 @@ address TemplateInterpreterGenerator::generate_math_entry(AbstractInterpreter::M } else { fn = CAST_FROM_FN_PTR(address, StubRoutines::dlog()); } - __ call(fn); + __ rt_call(fn); __ mv(ra, x9); break; case Interpreter::java_lang_math_log10 : @@ -241,7 +241,7 @@ address TemplateInterpreterGenerator::generate_math_entry(AbstractInterpreter::M } else { fn = CAST_FROM_FN_PTR(address, StubRoutines::dlog10()); } - __ call(fn); + __ rt_call(fn); __ mv(ra, x9); break; case Interpreter::java_lang_math_exp : @@ -254,7 +254,7 @@ address TemplateInterpreterGenerator::generate_math_entry(AbstractInterpreter::M } else { fn = CAST_FROM_FN_PTR(address, StubRoutines::dexp()); } - __ call(fn); + __ rt_call(fn); __ mv(ra, x9); break; case Interpreter::java_lang_math_pow : @@ -268,7 +268,7 @@ address TemplateInterpreterGenerator::generate_math_entry(AbstractInterpreter::M } else { fn = CAST_FROM_FN_PTR(address, StubRoutines::dpow()); } - __ call(fn); + __ rt_call(fn); __ mv(ra, x9); break; case Interpreter::java_lang_math_fmaD : diff --git a/src/hotspot/cpu/riscv/vm_version_riscv.cpp b/src/hotspot/cpu/riscv/vm_version_riscv.cpp index 3b8d8119a8e..67ada6729a9 100644 --- a/src/hotspot/cpu/riscv/vm_version_riscv.cpp +++ b/src/hotspot/cpu/riscv/vm_version_riscv.cpp @@ -154,10 +154,6 @@ void VM_Version::common_initialize() { unaligned_access.value() != MISALIGNED_FAST); } - if (FLAG_IS_DEFAULT(AlignVector)) { - FLAG_SET_DEFAULT(AlignVector, AvoidUnalignedAccesses); - } - // See JDK-8026049 // This machine has fast unaligned memory accesses if (FLAG_IS_DEFAULT(UseUnalignedAccesses)) { @@ -440,6 +436,10 @@ void VM_Version::c2_initialize() { warning("AES/CTR intrinsics are not available on this CPU"); FLAG_SET_DEFAULT(UseAESCTRIntrinsics, false); } + + if (FLAG_IS_DEFAULT(AlignVector)) { + FLAG_SET_DEFAULT(AlignVector, AvoidUnalignedAccesses); + } } #endif // COMPILER2 diff --git a/src/hotspot/cpu/s390/vm_version_s390.cpp b/src/hotspot/cpu/s390/vm_version_s390.cpp index a5195e753bb..f7f21c4c5ac 100644 --- a/src/hotspot/cpu/s390/vm_version_s390.cpp +++ b/src/hotspot/cpu/s390/vm_version_s390.cpp @@ -308,6 +308,12 @@ void VM_Version::initialize() { if (FLAG_IS_DEFAULT(UseMontgomerySquareIntrinsic)) { FLAG_SET_DEFAULT(UseMontgomerySquareIntrinsic, true); } + + // The OptoScheduling information is not maintained in s390.ad. + if (OptoScheduling) { + warning("OptoScheduling is not supported on this CPU."); + FLAG_SET_DEFAULT(OptoScheduling, false); + } #endif if (FLAG_IS_DEFAULT(UsePopCountInstruction)) { FLAG_SET_DEFAULT(UsePopCountInstruction, true); @@ -323,12 +329,6 @@ void VM_Version::initialize() { if (FLAG_IS_DEFAULT(UseUnalignedAccesses)) { FLAG_SET_DEFAULT(UseUnalignedAccesses, true); } - - // The OptoScheduling information is not maintained in s390.ad. - if (OptoScheduling) { - warning("OptoScheduling is not supported on this CPU."); - FLAG_SET_DEFAULT(OptoScheduling, false); - } } diff --git a/src/hotspot/cpu/x86/stubRoutines_x86.hpp b/src/hotspot/cpu/x86/stubRoutines_x86.hpp index af57fda23fd..0a6d091de8c 100644 --- a/src/hotspot/cpu/x86/stubRoutines_x86.hpp +++ b/src/hotspot/cpu/x86/stubRoutines_x86.hpp @@ -38,7 +38,7 @@ enum platform_dependent_constants { // AVX512 intrinsics add more code in 64-bit VM, // Windows have more code to save/restore registers _compiler_stubs_code_size = 20000 LP64_ONLY(+47000) WINDOWS_ONLY(+2000), - _final_stubs_code_size = 10000 LP64_ONLY(+20000) WINDOWS_ONLY(+2000) ZGC_ONLY(+20000) + _final_stubs_code_size = 10000 LP64_ONLY(+20000) WINDOWS_ONLY(+22000) ZGC_ONLY(+20000) }; class x86 { diff --git a/src/hotspot/share/cds/metaspaceShared.cpp b/src/hotspot/share/cds/metaspaceShared.cpp index f21b9c9060d..950076ac99f 100644 --- a/src/hotspot/share/cds/metaspaceShared.cpp +++ b/src/hotspot/share/cds/metaspaceShared.cpp @@ -145,15 +145,16 @@ size_t MetaspaceShared::core_region_alignment() { } static bool shared_base_valid(char* shared_base) { - // We check user input for SharedBaseAddress at dump time. We must weed out values - // we already know to be invalid later. + // We check user input for SharedBaseAddress at dump time. // At CDS runtime, "shared_base" will be the (attempted) mapping start. It will also // be the encoding base, since the the headers of archived base objects (and with Lilliput, // the prototype mark words) carry pre-computed narrow Klass IDs that refer to the mapping // start as base. // - // Therefore, "shared_base" must be later usable as encoding base. + // On AARCH64, The "shared_base" may not be later usable as encoding base, depending on the + // total size of the reserved area and the precomputed_narrow_klass_shift. This is checked + // before reserving memory. Here we weed out values already known to be invalid later. return AARCH64_ONLY(is_aligned(shared_base, 4 * G)) NOT_AARCH64(true); } @@ -985,8 +986,10 @@ bool MetaspaceShared::try_link_class(JavaThread* current, InstanceKlass* ik) { ik->external_name()); CLEAR_PENDING_EXCEPTION; SystemDictionaryShared::set_class_has_failed_verification(ik); + } else { + assert(!SystemDictionaryShared::has_class_failed_verification(ik), "sanity"); + ik->compute_has_loops_flag_for_methods(); } - ik->compute_has_loops_flag_for_methods(); BytecodeVerificationLocal = saved; return true; } else { @@ -1486,6 +1489,15 @@ char* MetaspaceShared::reserve_address_space_for_archives(FileMapInfo* static_ma const size_t total_range_size = archive_space_size + gap_size + class_space_size; + // Test that class space base address plus shift can be decoded by aarch64, when restored. + const int precomputed_narrow_klass_shift = ArchiveBuilder::precomputed_narrow_klass_shift(); + if (!CompressedKlassPointers::check_klass_decode_mode(base_address, precomputed_narrow_klass_shift, + total_range_size)) { + log_info(cds)("CDS initialization: Cannot use SharedBaseAddress " PTR_FORMAT " with precomputed shift %d.", + p2i(base_address), precomputed_narrow_klass_shift); + use_archive_base_addr = false; + } + assert(total_range_size > ccs_begin_offset, "must be"); if (use_windows_memory_mapping() && use_archive_base_addr) { if (base_address != nullptr) { @@ -1525,7 +1537,7 @@ char* MetaspaceShared::reserve_address_space_for_archives(FileMapInfo* static_ma } // Paranoid checks: - assert(base_address == nullptr || (address)total_space_rs.base() == base_address, + assert(!use_archive_base_addr || (address)total_space_rs.base() == base_address, "Sanity (" PTR_FORMAT " vs " PTR_FORMAT ")", p2i(base_address), p2i(total_space_rs.base())); assert(is_aligned(total_space_rs.base(), base_address_alignment), "Sanity"); assert(total_space_rs.size() == total_range_size, "Sanity"); diff --git a/src/hotspot/share/code/codeCache.cpp b/src/hotspot/share/code/codeCache.cpp index f0769e240dd..d84404b3569 100644 --- a/src/hotspot/share/code/codeCache.cpp +++ b/src/hotspot/share/code/codeCache.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -205,7 +205,7 @@ void CodeCache::initialize_heaps() { const bool cache_size_set = FLAG_IS_CMDLINE(ReservedCodeCacheSize); const size_t ps = page_size(false, 8); const size_t min_size = MAX2(os::vm_allocation_granularity(), ps); - const size_t min_cache_size = CompilerConfig::min_code_cache_size(); // Make sure we have enough space for VM internal code + const size_t min_cache_size = CodeCacheMinimumUseSpace DEBUG_ONLY(* 3); // Make sure we have enough space for VM internal code size_t cache_size = align_up(ReservedCodeCacheSize, min_size); // Prerequisites diff --git a/src/hotspot/share/compiler/compilationPolicy.cpp b/src/hotspot/share/compiler/compilationPolicy.cpp index 8fc70619abe..3364f5a3f56 100644 --- a/src/hotspot/share/compiler/compilationPolicy.cpp +++ b/src/hotspot/share/compiler/compilationPolicy.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -455,7 +455,7 @@ void CompilationPolicy::initialize() { c2_size = C2Compiler::initial_code_buffer_size(); #endif size_t buffer_size = c1_only ? c1_size : (c1_size/3 + 2*c2_size/3); - int max_count = (ReservedCodeCacheSize - (int)CompilerConfig::min_code_cache_size()) / (int)buffer_size; + int max_count = (ReservedCodeCacheSize - (CodeCacheMinimumUseSpace DEBUG_ONLY(* 3))) / (int)buffer_size; if (count > max_count) { // Lower the compiler count such that all buffers fit into the code cache count = MAX2(max_count, c1_only ? 1 : 2); diff --git a/src/hotspot/share/compiler/compilerDefinitions.cpp b/src/hotspot/share/compiler/compilerDefinitions.cpp index ad3d14012ff..938f183b9d8 100644 --- a/src/hotspot/share/compiler/compilerDefinitions.cpp +++ b/src/hotspot/share/compiler/compilerDefinitions.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -475,7 +475,8 @@ void CompilerConfig::set_jvmci_specific_flags() { bool CompilerConfig::check_args_consistency(bool status) { // Check lower bounds of the code cache - size_t min_code_cache_size = CompilerConfig::min_code_cache_size(); + // Template Interpreter code is approximately 3X larger in debug builds. + uint min_code_cache_size = CodeCacheMinimumUseSpace DEBUG_ONLY(* 3); if (ReservedCodeCacheSize < InitialCodeCacheSize) { jio_fprintf(defaultStream::error_stream(), "Invalid ReservedCodeCacheSize: %dK. Must be at least InitialCodeCacheSize=%dK.\n", diff --git a/src/hotspot/share/compiler/compilerDefinitions.hpp b/src/hotspot/share/compiler/compilerDefinitions.hpp index a72e82e32bd..bdaa6dffb8f 100644 --- a/src/hotspot/share/compiler/compilerDefinitions.hpp +++ b/src/hotspot/share/compiler/compilerDefinitions.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -148,8 +148,6 @@ class CompilerConfig : public AllStatic { inline static bool is_c2_or_jvmci_compiler_only(); inline static bool is_c2_or_jvmci_compiler_enabled(); - inline static size_t min_code_cache_size(); - private: static bool is_compilation_mode_selected(); static void set_compilation_policy_flags(); diff --git a/src/hotspot/share/compiler/compilerDefinitions.inline.hpp b/src/hotspot/share/compiler/compilerDefinitions.inline.hpp index 5557892669d..aa78323ea77 100644 --- a/src/hotspot/share/compiler/compilerDefinitions.inline.hpp +++ b/src/hotspot/share/compiler/compilerDefinitions.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,12 +25,6 @@ #ifndef SHARE_COMPILER_COMPILERDEFINITIONS_INLINE_HPP #define SHARE_COMPILER_COMPILERDEFINITIONS_INLINE_HPP -#ifdef COMPILER1 -#include "c1/c1_Compiler.hpp" -#endif -#ifdef COMPILER2 -#include "opto/c2compiler.hpp" -#endif #include "compiler/compilerDefinitions.hpp" #include "compiler/compiler_globals.hpp" @@ -138,13 +132,4 @@ inline bool CompilerConfig::is_c2_or_jvmci_compiler_enabled() { return is_c2_enabled() || is_jvmci_compiler_enabled(); } -inline size_t CompilerConfig::min_code_cache_size() { - size_t min_code_cache_size = CodeCacheMinimumUseSpace; - // Template Interpreter code is approximately 3X larger in debug builds. - DEBUG_ONLY(min_code_cache_size *= 3); - COMPILER1_PRESENT(min_code_cache_size += Compiler::code_buffer_size()); - COMPILER2_PRESENT(min_code_cache_size += C2Compiler::initial_code_buffer_size()); - return min_code_cache_size; -} - #endif // SHARE_COMPILER_COMPILERDEFINITIONS_INLINE_HPP diff --git a/src/hotspot/share/gc/shared/gcVMOperations.cpp b/src/hotspot/share/gc/shared/gcVMOperations.cpp index 4cc75f47459..4668c22009a 100644 --- a/src/hotspot/share/gc/shared/gcVMOperations.cpp +++ b/src/hotspot/share/gc/shared/gcVMOperations.cpp @@ -140,8 +140,8 @@ void VM_GC_Operation::doit_epilogue() { } bool VM_GC_HeapInspection::doit_prologue() { - if (_full_gc && UseZGC) { - // ZGC cannot perform a synchronous GC cycle from within the VM thread. + if (_full_gc && (UseZGC || UseShenandoahGC)) { + // ZGC and Shenandoah cannot perform a synchronous GC cycle from within the VM thread. // So VM_GC_HeapInspection::collect() is a noop. To respect the _full_gc // flag a synchronous GC cycle is performed from the caller thread in the // prologue. diff --git a/src/hotspot/share/gc/shared/genArguments.cpp b/src/hotspot/share/gc/shared/genArguments.cpp index 76f9f6d4052..c94ca56722f 100644 --- a/src/hotspot/share/gc/shared/genArguments.cpp +++ b/src/hotspot/share/gc/shared/genArguments.cpp @@ -37,7 +37,11 @@ size_t MinNewSize = 0; size_t MinOldSize = 0; size_t MaxOldSize = 0; -size_t OldSize = 0; +// If InitialHeapSize or MinHeapSize is not set on cmdline, this variable, +// together with NewSize, is used to derive them. +// Using the same value when it was a configurable flag to avoid breakage. +// See more in JDK-8346005 +size_t OldSize = ScaleForWordSize(4*M); size_t GenAlignment = 0; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.cpp index 5b8afc52b93..2ad35fcb288 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.cpp @@ -180,8 +180,8 @@ void ShenandoahGenerationalHeap::gc_threads_do(ThreadClosure* tcl) const { } void ShenandoahGenerationalHeap::stop() { - regulator_thread()->stop(); ShenandoahHeap::stop(); + regulator_thread()->stop(); } void ShenandoahGenerationalHeap::evacuate_collection_set(bool concurrent) { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp index 6ef66926b72..dcebef5d772 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp @@ -538,7 +538,6 @@ ShenandoahHeap::ShenandoahHeap(ShenandoahCollectorPolicy* policy) : _pacer(nullptr), _verifier(nullptr), _phase_timings(nullptr), - _mmu_tracker(), _monitoring_support(nullptr), _memory_pool(nullptr), _stw_memory_manager("Shenandoah Pauses"), @@ -632,6 +631,8 @@ class ShenandoahInitWorkerGCLABClosure : public ThreadClosure { void ShenandoahHeap::post_initialize() { CollectedHeap::post_initialize(); + + // Schedule periodic task to report on gc thread CPU utilization _mmu_tracker.initialize(); MutexLocker ml(Threads_lock); @@ -1467,6 +1468,18 @@ size_t ShenandoahHeap::max_tlab_size() const { return ShenandoahHeapRegion::max_tlab_size_words(); } +void ShenandoahHeap::collect_as_vm_thread(GCCause::Cause cause) { + // These requests are ignored because we can't easily have Shenandoah jump into + // a synchronous (degenerated or full) cycle while it is in the middle of a concurrent + // cycle. We _could_ cancel the concurrent cycle and then try to run a cycle directly + // on the VM thread, but this would confuse the control thread mightily and doesn't + // seem worth the trouble. Instead, we will have the caller thread run (and wait for) a + // concurrent cycle in the prologue of the heap inspect/dump operation. This is how + // other concurrent collectors in the JVM handle this scenario as well. + assert(Thread::current()->is_VM_thread(), "Should be the VM thread"); + guarantee(cause == GCCause::_heap_dump || cause == GCCause::_heap_inspection, "Invalid cause"); +} + void ShenandoahHeap::collect(GCCause::Cause cause) { control_thread()->request_gc(cause); } @@ -1547,7 +1560,9 @@ void ShenandoahHeap::set_active_generation() { void ShenandoahHeap::on_cycle_start(GCCause::Cause cause, ShenandoahGeneration* generation) { shenandoah_policy()->record_collection_cause(cause); - assert(gc_cause() == GCCause::_no_gc, "Over-writing cause"); + const GCCause::Cause current = gc_cause(); + assert(current == GCCause::_no_gc, "Over-writing cause: %s, with: %s", + GCCause::to_string(current), GCCause::to_string(cause)); assert(_gc_generation == nullptr, "Over-writing _gc_generation"); set_gc_cause(cause); @@ -2084,6 +2099,9 @@ void ShenandoahHeap::stop() { // Step 0. Notify policy to disable event recording and prevent visiting gc threads during shutdown _shenandoah_policy->record_shutdown(); + // Step 0a. Stop reporting on gc thread cpu utilization + mmu_tracker()->stop(); + // Step 1. Notify control thread that we are in shutdown. // Note that we cannot do that with stop(), because stop() is blocking and waits for the actual shutdown. // Doing stop() here would wait for the normal GC cycle to complete, never falling through to cancel below. diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp index a9a793f9e60..5a9ff374a65 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp @@ -608,6 +608,7 @@ class ShenandoahHeap : public CollectedHeap { MemRegion reserved_region() const { return _reserved; } bool is_in_reserved(const void* addr) const { return _reserved.contains(addr); } + void collect_as_vm_thread(GCCause::Cause cause) override; void collect(GCCause::Cause cause) override; void do_full_collection(bool clear_all_soft_refs) override; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahMemoryPool.cpp b/src/hotspot/share/gc/shenandoah/shenandoahMemoryPool.cpp index 6cbb5454ac1..9350f44585f 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahMemoryPool.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahMemoryPool.cpp @@ -93,11 +93,6 @@ size_t ShenandoahGenerationalMemoryPool::used_in_bytes() { return _generation->used(); } -size_t ShenandoahGenerationalMemoryPool::max_size() const { - return _generation->max_capacity(); -} - - ShenandoahYoungGenMemoryPool::ShenandoahYoungGenMemoryPool(ShenandoahHeap* heap) : ShenandoahGenerationalMemoryPool(heap, "Shenandoah Young Gen", diff --git a/src/hotspot/share/gc/shenandoah/shenandoahMemoryPool.hpp b/src/hotspot/share/gc/shenandoah/shenandoahMemoryPool.hpp index e26d61a3a6c..ccdfdddede9 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahMemoryPool.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahMemoryPool.hpp @@ -55,7 +55,6 @@ class ShenandoahGenerationalMemoryPool: public ShenandoahMemoryPool { explicit ShenandoahGenerationalMemoryPool(ShenandoahHeap* heap, const char* name, ShenandoahGeneration* generation); MemoryUsage get_memory_usage() override; size_t used_in_bytes() override; - size_t max_size() const override; }; class ShenandoahYoungGenMemoryPool : public ShenandoahGenerationalMemoryPool { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahMmuTracker.cpp b/src/hotspot/share/gc/shenandoah/shenandoahMmuTracker.cpp index f4cbdbdd493..d9cec36e6c9 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahMmuTracker.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahMmuTracker.cpp @@ -48,6 +48,7 @@ class ThreadTimeAccumulator : public ThreadClosure { size_t total_time; ThreadTimeAccumulator() : total_time(0) {} void do_thread(Thread* thread) override { + assert(!thread->has_terminated(), "Cannot get cpu time for terminated thread: " UINTX_FORMAT, thread->osthread()->thread_id_for_printing()); total_time += os::thread_cpu_time(thread); } }; @@ -65,7 +66,6 @@ ShenandoahMmuTracker::ShenandoahMmuTracker() : } ShenandoahMmuTracker::~ShenandoahMmuTracker() { - _mmu_periodic_task->disenroll(); delete _mmu_periodic_task; } @@ -175,6 +175,10 @@ void ShenandoahMmuTracker::report() { log_debug(gc)("Periodic Sample: GCU = %.3f%%, MU = %.3f%% during most recent %.1fs", gcu * 100, mu * 100, time_delta); } +void ShenandoahMmuTracker::stop() const { + _mmu_periodic_task->disenroll(); +} + void ShenandoahMmuTracker::initialize() { // initialize static data _active_processors = os::initial_active_processor_count(); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahMmuTracker.hpp b/src/hotspot/share/gc/shenandoah/shenandoahMmuTracker.hpp index 53b6fdada55..89dbf921cd4 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahMmuTracker.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahMmuTracker.hpp @@ -101,6 +101,10 @@ class ShenandoahMmuTracker { // GCPauseIntervalMillis and defaults to 5 seconds. This method computes // the MMU over the elapsed interval and records it in a running average. void report(); + + // Unenrolls the periodic task that collects CPU utilization for GC threads. This must happen _before_ the + // gc threads are stopped and terminated. + void stop() const; }; #endif //SHARE_GC_SHENANDOAH_SHENANDOAHMMUTRACKER_HPP diff --git a/src/hotspot/share/oops/compressedKlass.cpp b/src/hotspot/share/oops/compressedKlass.cpp index f3c6fe92897..97415cf6e85 100644 --- a/src/hotspot/share/oops/compressedKlass.cpp +++ b/src/hotspot/share/oops/compressedKlass.cpp @@ -30,6 +30,7 @@ #include "runtime/java.hpp" #include "runtime/os.hpp" #include "utilities/debug.hpp" +#include "utilities/formatBuffer.hpp" #include "utilities/globalDefinitions.hpp" #include "utilities/ostream.hpp" @@ -176,6 +177,12 @@ void CompressedKlassPointers::initialize_for_given_encoding(address addr, size_t calc_lowest_highest_narrow_klass_id(); + // This has already been checked for SharedBaseAddress and if this fails, it's a bug in the allocation code. + if (!set_klass_decode_mode()) { + fatal("base=" PTR_FORMAT " given with shift %d, cannot be used to encode class pointers", + p2i(_base), _shift); + } + DEBUG_ONLY(sanity_check_after_initialization();) } @@ -267,6 +274,20 @@ void CompressedKlassPointers::initialize(address addr, size_t len) { calc_lowest_highest_narrow_klass_id(); + // Initialize klass decode mode and check compability with decode instructions + if (!set_klass_decode_mode()) { + + // Give fatal error if this is a specified address + if ((address)CompressedClassSpaceBaseAddress == _base) { + vm_exit_during_initialization( + err_msg("CompressedClassSpaceBaseAddress=" PTR_FORMAT " given with shift %d, cannot be used to encode class pointers", + CompressedClassSpaceBaseAddress, _shift)); + } else { + // If this fails, it's a bug in the allocation code. + fatal("CompressedClassSpaceBaseAddress=" PTR_FORMAT " given with shift %d, cannot be used to encode class pointers", + p2i(_base), _shift); + } + } #ifdef ASSERT sanity_check_after_initialization(); #endif diff --git a/src/hotspot/share/oops/compressedKlass.hpp b/src/hotspot/share/oops/compressedKlass.hpp index 9e3a09d73b9..dd54c8130eb 100644 --- a/src/hotspot/share/oops/compressedKlass.hpp +++ b/src/hotspot/share/oops/compressedKlass.hpp @@ -258,6 +258,15 @@ class CompressedKlassPointers : public AllStatic { is_aligned(addr, klass_alignment_in_bytes()); } +#if defined(AARCH64) && !defined(ZERO) + // Check that with the given base, shift and range, aarch64 code can encode and decode the klass pointer. + static bool check_klass_decode_mode(address base, int shift, const size_t range); + // Called after initialization. + static bool set_klass_decode_mode(); +#else + static bool check_klass_decode_mode(address base, int shift, const size_t range) { return true; } + static bool set_klass_decode_mode() { return true; } +#endif }; #endif // SHARE_OOPS_COMPRESSEDKLASS_HPP diff --git a/src/hotspot/share/opto/addnode.cpp b/src/hotspot/share/opto/addnode.cpp index 4215124b0d4..813371ed078 100644 --- a/src/hotspot/share/opto/addnode.cpp +++ b/src/hotspot/share/opto/addnode.cpp @@ -395,159 +395,9 @@ Node* AddNode::IdealIL(PhaseGVN* phase, bool can_reshape, BasicType bt) { } } - // Convert a + a + ... + a into a*n - Node* serial_additions = convert_serial_additions(phase, bt); - if (serial_additions != nullptr) { - return serial_additions; - } - return AddNode::Ideal(phase, can_reshape); } -// Try to convert a serial of additions into a single multiplication. Also convert `(a * CON) + a` to `(CON + 1) * a` as -// a side effect. On success, a new MulNode is returned. -Node* AddNode::convert_serial_additions(PhaseGVN* phase, BasicType bt) { - // We need to make sure that the current AddNode is not part of a MulNode that has already been optimized to a - // power-of-2 addition (e.g., 3 * a => (a << 2) + a). Without this check, GVN would keep trying to optimize the same - // node and can't progress. For example, 3 * a => (a << 2) + a => 3 * a => (a << 2) + a => ... - if (find_power_of_two_addition_pattern(this, bt, nullptr) != nullptr) { - return nullptr; - } - - Node* in1 = in(1); - Node* in2 = in(2); - jlong multiplier; - - // While multiplications can be potentially optimized to power-of-2 subtractions (e.g., a * 7 => (a << 3) - a), - // (x - y) + y => x is already handled by the Identity() methods. So, we don't need to check for that pattern here. - if (find_simple_addition_pattern(in1, bt, &multiplier) == in2 - || find_simple_lshift_pattern(in1, bt, &multiplier) == in2 - || find_simple_multiplication_pattern(in1, bt, &multiplier) == in2 - || find_power_of_two_addition_pattern(in1, bt, &multiplier) == in2) { - multiplier++; // +1 for the in2 term - - Node* con = (bt == T_INT) - ? (Node*) phase->intcon((jint) multiplier) // intentional type narrowing to allow overflow at max_jint - : (Node*) phase->longcon(multiplier); - return MulNode::make(con, in2, bt); - } - - return nullptr; -} - -// Try to match `a + a`. On success, return `a` and set `2` as `multiplier`. -// The method matches `n` for pattern: AddNode(a, a). -Node* AddNode::find_simple_addition_pattern(Node* n, BasicType bt, jlong* multiplier) { - if (n->Opcode() == Op_Add(bt) && n->in(1) == n->in(2)) { - *multiplier = 2; - return n->in(1); - } - - return nullptr; -} - -// Try to match `a << CON`. On success, return `a` and set `1 << CON` as `multiplier`. -// Match `n` for pattern: LShiftNode(a, CON). -// Note that the power-of-2 multiplication optimization could potentially convert a MulNode to this pattern. -Node* AddNode::find_simple_lshift_pattern(Node* n, BasicType bt, jlong* multiplier) { - // Note that power-of-2 multiplication optimization could potentially convert a MulNode to this pattern - if (n->Opcode() == Op_LShift(bt) && n->in(2)->is_Con()) { - Node* con = n->in(2); - if (con->is_top()) { - return nullptr; - } - - *multiplier = ((jlong) 1 << con->get_int()); - return n->in(1); - } - - return nullptr; -} - -// Try to match `CON * a`. On success, return `a` and set `CON` as `multiplier`. -// Match `n` for patterns: -// - MulNode(CON, a) -// - MulNode(a, CON) -Node* AddNode::find_simple_multiplication_pattern(Node* n, BasicType bt, jlong* multiplier) { - // This optimization technically only produces MulNode(CON, a), but we might as match MulNode(a, CON), too. - if (n->Opcode() == Op_Mul(bt) && (n->in(1)->is_Con() || n->in(2)->is_Con())) { - Node* con = n->in(1); - Node* base = n->in(2); - - // swap ConNode to lhs for easier matching - if (!con->is_Con()) { - swap(con, base); - } - - if (con->is_top()) { - return nullptr; - } - - *multiplier = con->get_integer_as_long(bt); - return base; - } - - return nullptr; -} - -// Try to match `(a << CON1) + (a << CON2)`. On success, return `a` and set `(1 << CON1) + (1 << CON2)` as `multiplier`. -// Match `n` for patterns: -// - AddNode(LShiftNode(a, CON), LShiftNode(a, CON)/a) -// - AddNode(LShiftNode(a, CON)/a, LShiftNode(a, CON)) -// given that lhs is different from rhs. -// Note that one of the term of the addition could simply be `a` (i.e., a << 0). Calling this function with `multiplier` -// being null is safe. -Node* AddNode::find_power_of_two_addition_pattern(Node* n, BasicType bt, jlong* multiplier) { - if (n->Opcode() == Op_Add(bt) && n->in(1) != n->in(2)) { - Node* lhs = n->in(1); - Node* rhs = n->in(2); - - // swap LShiftNode to lhs for easier matching - if (lhs->Opcode() != Op_LShift(bt)) { - swap(lhs, rhs); - } - - // AddNode(LShiftNode(a, CON), *)? - if (lhs->Opcode() != Op_LShift(bt) || !lhs->in(2)->is_Con()) { - return nullptr; - } - - jlong lhs_multiplier = 0; - if (multiplier != nullptr) { - Node* con = lhs->in(2); - if (con->is_top()) { - return nullptr; - } - - lhs_multiplier = (jlong) 1 << con->get_int(); - } - - // AddNode(LShiftNode(a, CON), a)? - if (lhs->in(1) == rhs) { - if (multiplier != nullptr) { - *multiplier = lhs_multiplier + 1; - } - - return rhs; - } - - // AddNode(LShiftNode(a, CON), LShiftNode(a, CON2))? - if (rhs->Opcode() == Op_LShift(bt) && lhs->in(1) == rhs->in(1) && rhs->in(2)->is_Con()) { - if (multiplier != nullptr) { - Node* con = rhs->in(2); - if (con->is_top()) { - return nullptr; - } - - *multiplier = lhs_multiplier + ((jlong) 1 << con->get_int()); - } - - return lhs->in(1); - } - return nullptr; - } - return nullptr; -} Node* AddINode::Ideal(PhaseGVN* phase, bool can_reshape) { Node* in1 = in(1); diff --git a/src/hotspot/share/opto/addnode.hpp b/src/hotspot/share/opto/addnode.hpp index 8afbb440572..8879606954a 100644 --- a/src/hotspot/share/opto/addnode.hpp +++ b/src/hotspot/share/opto/addnode.hpp @@ -42,13 +42,6 @@ typedef const Pair ConstAddOperands; // by virtual functions. class AddNode : public Node { virtual uint hash() const; - - Node* convert_serial_additions(PhaseGVN* phase, BasicType bt); - static Node* find_simple_addition_pattern(Node* n, BasicType bt, jlong* multiplier); - static Node* find_simple_lshift_pattern(Node* n, BasicType bt, jlong* multiplier); - static Node* find_simple_multiplication_pattern(Node* n, BasicType bt, jlong* multiplier); - static Node* find_power_of_two_addition_pattern(Node* n, BasicType bt, jlong* multiplier); - public: AddNode( Node *in1, Node *in2 ) : Node(nullptr,in1,in2) { init_class_id(Class_Add); diff --git a/src/hotspot/share/opto/library_call.cpp b/src/hotspot/share/opto/library_call.cpp index 1072a5d6a24..fcf6b920884 100644 --- a/src/hotspot/share/opto/library_call.cpp +++ b/src/hotspot/share/opto/library_call.cpp @@ -4262,7 +4262,7 @@ bool LibraryCallKit::inline_native_subtype_check() { //---------------------generate_array_guard_common------------------------ Node* LibraryCallKit::generate_array_guard_common(Node* kls, RegionNode* region, - bool obj_array, bool not_array) { + bool obj_array, bool not_array, Node** obj) { if (stopped()) { return nullptr; @@ -4304,7 +4304,14 @@ Node* LibraryCallKit::generate_array_guard_common(Node* kls, RegionNode* region, // invert the test if we are looking for a non-array if (not_array) btest = BoolTest(btest).negate(); Node* bol = _gvn.transform(new BoolNode(cmp, btest)); - return generate_fair_guard(bol, region); + Node* ctrl = generate_fair_guard(bol, region); + Node* is_array_ctrl = not_array ? control() : ctrl; + if (obj != nullptr && is_array_ctrl != nullptr && is_array_ctrl != top()) { + // Keep track of the fact that 'obj' is an array to prevent + // array specific accesses from floating above the guard. + *obj = _gvn.transform(new CastPPNode(is_array_ctrl, *obj, TypeAryPtr::BOTTOM)); + } + return ctrl; } @@ -4399,7 +4406,7 @@ bool LibraryCallKit::inline_native_getLength() { if (stopped()) return true; // Deoptimize if it is a non-array. - Node* non_array = generate_non_array_guard(load_object_klass(array), nullptr); + Node* non_array = generate_non_array_guard(load_object_klass(array), nullptr, &array); if (non_array != nullptr) { PreserveJVMState pjvms(this); @@ -5259,12 +5266,13 @@ bool LibraryCallKit::inline_native_clone(bool is_virtual) { record_for_igvn(result_reg); Node* obj_klass = load_object_klass(obj); - Node* array_ctl = generate_array_guard(obj_klass, (RegionNode*)nullptr); + Node* array_obj = obj; + Node* array_ctl = generate_array_guard(obj_klass, (RegionNode*)nullptr, &array_obj); if (array_ctl != nullptr) { // It's an array. PreserveJVMState pjvms(this); set_control(array_ctl); - Node* obj_length = load_array_length(obj); + Node* obj_length = load_array_length(array_obj); Node* array_size = nullptr; // Size of the array without object alignment padding. Node* alloc_obj = new_array(obj_klass, obj_length, 0, &array_size, /*deoptimize_on_exception=*/true); @@ -5278,7 +5286,7 @@ bool LibraryCallKit::inline_native_clone(bool is_virtual) { set_control(is_obja); // Generate a direct call to the right arraycopy function(s). // Clones are always tightly coupled. - ArrayCopyNode* ac = ArrayCopyNode::make(this, true, obj, intcon(0), alloc_obj, intcon(0), obj_length, true, false); + ArrayCopyNode* ac = ArrayCopyNode::make(this, true, array_obj, intcon(0), alloc_obj, intcon(0), obj_length, true, false); ac->set_clone_oop_array(); Node* n = _gvn.transform(ac); assert(n == ac, "cannot disappear"); @@ -5299,7 +5307,7 @@ bool LibraryCallKit::inline_native_clone(bool is_virtual) { // the object.) if (!stopped()) { - copy_to_clone(obj, alloc_obj, array_size, true); + copy_to_clone(array_obj, alloc_obj, array_size, true); // Present the results of the copy. result_reg->init_req(_array_path, control()); @@ -5920,8 +5928,8 @@ bool LibraryCallKit::inline_arraycopy() { record_for_igvn(slow_region); // (1) src and dest are arrays. - generate_non_array_guard(load_object_klass(src), slow_region); - generate_non_array_guard(load_object_klass(dest), slow_region); + generate_non_array_guard(load_object_klass(src), slow_region, &src); + generate_non_array_guard(load_object_klass(dest), slow_region, &dest); // (2) src and dest arrays must have elements of the same BasicType // done at macro expansion or at Ideal transformation time @@ -8537,7 +8545,7 @@ bool LibraryCallKit::inline_getObjectSize() { PhiNode* result_val = new PhiNode(result_reg, TypeLong::LONG); record_for_igvn(result_reg); - Node* array_ctl = generate_array_guard(klass_node, nullptr); + Node* array_ctl = generate_array_guard(klass_node, nullptr, &obj); if (array_ctl != nullptr) { // Array case: size is round(header + element_size*arraylength). // Since arraylength is different for every array instance, we have to diff --git a/src/hotspot/share/opto/library_call.hpp b/src/hotspot/share/opto/library_call.hpp index c5437e3bf73..25a853a6fef 100644 --- a/src/hotspot/share/opto/library_call.hpp +++ b/src/hotspot/share/opto/library_call.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -163,20 +163,20 @@ class LibraryCallKit : public GraphKit { RegionNode* region); Node* generate_interface_guard(Node* kls, RegionNode* region); Node* generate_hidden_class_guard(Node* kls, RegionNode* region); - Node* generate_array_guard(Node* kls, RegionNode* region) { - return generate_array_guard_common(kls, region, false, false); + Node* generate_array_guard(Node* kls, RegionNode* region, Node** obj = nullptr) { + return generate_array_guard_common(kls, region, false, false, obj); } - Node* generate_non_array_guard(Node* kls, RegionNode* region) { - return generate_array_guard_common(kls, region, false, true); + Node* generate_non_array_guard(Node* kls, RegionNode* region, Node** obj = nullptr) { + return generate_array_guard_common(kls, region, false, true, obj); } - Node* generate_objArray_guard(Node* kls, RegionNode* region) { - return generate_array_guard_common(kls, region, true, false); + Node* generate_objArray_guard(Node* kls, RegionNode* region, Node** obj = nullptr) { + return generate_array_guard_common(kls, region, true, false, obj); } - Node* generate_non_objArray_guard(Node* kls, RegionNode* region) { - return generate_array_guard_common(kls, region, true, true); + Node* generate_non_objArray_guard(Node* kls, RegionNode* region, Node** obj = nullptr) { + return generate_array_guard_common(kls, region, true, true, obj); } Node* generate_array_guard_common(Node* kls, RegionNode* region, - bool obj_array, bool not_array); + bool obj_array, bool not_array, Node** obj = nullptr); Node* generate_virtual_guard(Node* obj_klass, RegionNode* slow_region); CallJavaNode* generate_method_call(vmIntrinsicID method_id, bool is_virtual, bool is_static, bool res_not_null); CallJavaNode* generate_method_call_static(vmIntrinsicID method_id, bool res_not_null) { diff --git a/src/hotspot/share/opto/subnode.cpp b/src/hotspot/share/opto/subnode.cpp index 445eb168214..f1eca4682bd 100644 --- a/src/hotspot/share/opto/subnode.cpp +++ b/src/hotspot/share/opto/subnode.cpp @@ -1623,27 +1623,17 @@ Node *BoolNode::Ideal(PhaseGVN *phase, bool can_reshape) { return new BoolNode( ncmp, _test.negate() ); } - // Change ((x & (m - 1)) u< m) into (m > 0) - // This is the off-by-one variant of ((x & m) u<= m) - if (cop == Op_CmpU && - _test._test == BoolTest::lt && - cmp1_op == Op_AndI) { - Node* l = cmp1->in(1); - Node* r = cmp1->in(2); - for (int repeat = 0; repeat < 2; repeat++) { - bool match = r->Opcode() == Op_AddI && r->in(2)->find_int_con(0) == -1 && - r->in(1) == cmp2; - if (match) { - // arraylength known to be non-negative, so a (arraylength != 0) is sufficient, - // but to be compatible with the array range check pattern, use (arraylength u> 0) - Node* ncmp = cmp2->Opcode() == Op_LoadRange - ? phase->transform(new CmpUNode(cmp2, phase->intcon(0))) - : phase->transform(new CmpINode(cmp2, phase->intcon(0))); - return new BoolNode(ncmp, BoolTest::gt); - } else { - // commute and try again - l = cmp1->in(2); - r = cmp1->in(1); + // Transform: "((x & (m - 1)) u 0)" + // This is case [CMPU_MASK] which is further described at the method comment of BoolNode::Value_cmpu_and_mask(). + if (cop == Op_CmpU && _test._test == BoolTest::lt && cmp1_op == Op_AndI) { + Node* m = cmp2; // RHS: m + for (int add_idx = 1; add_idx <= 2; add_idx++) { // LHS: "(m + (-1)) & x" or "x & (m + (-1))"? + Node* maybe_m_minus_1 = cmp1->in(add_idx); + if (maybe_m_minus_1->Opcode() == Op_AddI && + maybe_m_minus_1->in(2)->find_int_con(0) == -1 && + maybe_m_minus_1->in(1) == m) { + Node* m_cmpu_0 = phase->transform(new CmpUNode(m, phase->intcon(0))); + return new BoolNode(m_cmpu_0, BoolTest::gt); } } } @@ -1809,9 +1799,57 @@ Node *BoolNode::Ideal(PhaseGVN *phase, bool can_reshape) { // } } -//------------------------------Value------------------------------------------ -// Change ((x & m) u<= m) or ((m & x) u<= m) to always true -// Same with ((x & m) u< m+1) and ((m & x) u< m+1) +// We use the following Lemmas/insights for the following two transformations (1) and (2): +// x & y <=u y, for any x and y (Lemma 1, masking always results in a smaller unsigned number) +// y u 0) +// This is the off-by-one variant of the above. +// +// We now prove that this replacement is correct. This is the same as proving +// "m >u 0" if and only if "x & (m - 1) u 0 <=> x & (m - 1) m >u 0": +// We prove this by contradiction: +// Assume m <=u 0 which is equivalent to m == 0: +// and thus +// x & (m - 1) u 0 => x & (m - 1) u 0, no underflow of "m - 1" +// +// +// Note that the signed version of "m > 0": +// m > 0 <=> x & (m - 1) 0 +// is false which is a contradiction. +// +// (1a) and (1b) is covered by this method since we can directly return a true value as type while (2) is covered +// in BoolNode::Ideal since we create a new non-constant node (see [CMPU_MASK]). const Type* BoolNode::Value_cmpu_and_mask(PhaseValues* phase) const { Node* cmp = in(1); if (cmp != nullptr && cmp->Opcode() == Op_CmpU) { @@ -1819,14 +1857,21 @@ const Type* BoolNode::Value_cmpu_and_mask(PhaseValues* phase) const { Node* cmp2 = cmp->in(2); if (cmp1->Opcode() == Op_AndI) { - Node* bound = nullptr; + Node* m = nullptr; if (_test._test == BoolTest::le) { - bound = cmp2; + // (1a) "((x & m) <=u m)", cmp2 = m + m = cmp2; } else if (_test._test == BoolTest::lt && cmp2->Opcode() == Op_AddI && cmp2->in(2)->find_int_con(0) == 1) { - bound = cmp2->in(1); + // (1b) "(x & m) in(1); + const TypeInt* rhs_m_type = phase->type(rhs_m)->isa_int(); + if (rhs_m_type->_lo > -1 || rhs_m_type->_hi < -1) { + // Exclude any case where m == -1 is possible. + m = rhs_m; + } } - if (cmp1->in(2) == bound || cmp1->in(1) == bound) { + if (cmp1->in(2) == m || cmp1->in(1) == m) { return TypeInt::ONE; } } diff --git a/src/hotspot/share/opto/type.cpp b/src/hotspot/share/opto/type.cpp index 407a4a20a9b..2424daf81e3 100644 --- a/src/hotspot/share/opto/type.cpp +++ b/src/hotspot/share/opto/type.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -582,6 +582,7 @@ void Type::Initialize_shared(Compile* current) { TypeAryPtr::_array_interfaces = TypeInterfaces::make(&array_interfaces); TypeAryKlassPtr::_array_interfaces = TypeAryPtr::_array_interfaces; + TypeAryPtr::BOTTOM = TypeAryPtr::make(TypePtr::BotPTR, TypeAry::make(Type::BOTTOM, TypeInt::POS), nullptr, false, Type::OffsetBot); TypeAryPtr::RANGE = TypeAryPtr::make( TypePtr::BotPTR, TypeAry::make(Type::BOTTOM,TypeInt::POS), nullptr /* current->env()->Object_klass() */, false, arrayOopDesc::length_offset_in_bytes()); TypeAryPtr::NARROWOOPS = TypeAryPtr::make(TypePtr::BotPTR, TypeAry::make(TypeNarrowOop::BOTTOM, TypeInt::POS), nullptr /*ciArrayKlass::make(o)*/, false, Type::OffsetBot); @@ -4682,16 +4683,17 @@ bool TypeAryKlassPtr::is_meet_subtype_of_helper(const TypeKlassPtr *other, bool //============================================================================= // Convenience common pre-built types. -const TypeAryPtr *TypeAryPtr::RANGE; -const TypeAryPtr *TypeAryPtr::OOPS; -const TypeAryPtr *TypeAryPtr::NARROWOOPS; -const TypeAryPtr *TypeAryPtr::BYTES; -const TypeAryPtr *TypeAryPtr::SHORTS; -const TypeAryPtr *TypeAryPtr::CHARS; -const TypeAryPtr *TypeAryPtr::INTS; -const TypeAryPtr *TypeAryPtr::LONGS; -const TypeAryPtr *TypeAryPtr::FLOATS; -const TypeAryPtr *TypeAryPtr::DOUBLES; +const TypeAryPtr* TypeAryPtr::BOTTOM; +const TypeAryPtr* TypeAryPtr::RANGE; +const TypeAryPtr* TypeAryPtr::OOPS; +const TypeAryPtr* TypeAryPtr::NARROWOOPS; +const TypeAryPtr* TypeAryPtr::BYTES; +const TypeAryPtr* TypeAryPtr::SHORTS; +const TypeAryPtr* TypeAryPtr::CHARS; +const TypeAryPtr* TypeAryPtr::INTS; +const TypeAryPtr* TypeAryPtr::LONGS; +const TypeAryPtr* TypeAryPtr::FLOATS; +const TypeAryPtr* TypeAryPtr::DOUBLES; //------------------------------make------------------------------------------- const TypeAryPtr *TypeAryPtr::make(PTR ptr, const TypeAry *ary, ciKlass* k, bool xk, int offset, diff --git a/src/hotspot/share/opto/type.hpp b/src/hotspot/share/opto/type.hpp index f6b7efcae3b..9bb86fc94e6 100644 --- a/src/hotspot/share/opto/type.hpp +++ b/src/hotspot/share/opto/type.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1470,16 +1470,17 @@ class TypeAryPtr : public TypeOopPtr { virtual const TypeKlassPtr* as_klass_type(bool try_for_exact = false) const; // Convenience common pre-built types. - static const TypeAryPtr *RANGE; - static const TypeAryPtr *OOPS; - static const TypeAryPtr *NARROWOOPS; - static const TypeAryPtr *BYTES; - static const TypeAryPtr *SHORTS; - static const TypeAryPtr *CHARS; - static const TypeAryPtr *INTS; - static const TypeAryPtr *LONGS; - static const TypeAryPtr *FLOATS; - static const TypeAryPtr *DOUBLES; + static const TypeAryPtr* BOTTOM; + static const TypeAryPtr* RANGE; + static const TypeAryPtr* OOPS; + static const TypeAryPtr* NARROWOOPS; + static const TypeAryPtr* BYTES; + static const TypeAryPtr* SHORTS; + static const TypeAryPtr* CHARS; + static const TypeAryPtr* INTS; + static const TypeAryPtr* LONGS; + static const TypeAryPtr* FLOATS; + static const TypeAryPtr* DOUBLES; // selects one of the above: static const TypeAryPtr *get_array_body_type(BasicType elem) { assert((uint)elem <= T_CONFLICT && _array_body_type[elem] != nullptr, "bad elem type"); diff --git a/src/hotspot/share/opto/vectorIntrinsics.cpp b/src/hotspot/share/opto/vectorIntrinsics.cpp index 3d20b22a175..63bbc0443b6 100644 --- a/src/hotspot/share/opto/vectorIntrinsics.cpp +++ b/src/hotspot/share/opto/vectorIntrinsics.cpp @@ -1637,8 +1637,9 @@ bool LibraryCallKit::inline_vector_reduction() { int opc = VectorSupport::vop2ideal(opr->get_con(), elem_bt); int sopc = ReductionNode::opcode(opc, elem_bt); + // Ensure reduction operation for lanewise operation // When using mask, mask use type needs to be VecMaskUseLoad. - if (!arch_supports_vector(sopc, num_elem, elem_bt, is_masked_op ? VecMaskUseLoad : VecMaskNotUsed)) { + if (sopc == opc || !arch_supports_vector(sopc, num_elem, elem_bt, is_masked_op ? VecMaskUseLoad : VecMaskNotUsed)) { log_if_needed(" ** not supported: arity=1 op=%d/reduce vlen=%d etype=%s is_masked_op=%d", sopc, num_elem, type2name(elem_bt), is_masked_op ? 1 : 0); return false; diff --git a/src/hotspot/share/opto/vectornode.cpp b/src/hotspot/share/opto/vectornode.cpp index dedac80d102..03e1e7ef247 100644 --- a/src/hotspot/share/opto/vectornode.cpp +++ b/src/hotspot/share/opto/vectornode.cpp @@ -1466,6 +1466,9 @@ bool VectorCastNode::implemented(int opc, uint vlen, BasicType src_type, BasicTy if (is_java_primitive(dst_type) && is_java_primitive(src_type) && (vlen > 1) && is_power_of_2(vlen) && + // In rare case, the input to the VectorCast could be a Replicate node. We need to make sure creating is supported: + // check the src_type: + VectorNode::vector_size_supported_auto_vectorization(src_type, vlen) && VectorNode::vector_size_supported_auto_vectorization(dst_type, vlen)) { int vopc = VectorCastNode::opcode(opc, src_type); return vopc > 0 && Matcher::match_rule_supported_auto_vectorization(vopc, vlen, dst_type); diff --git a/src/hotspot/share/prims/jvmtiEventController.cpp b/src/hotspot/share/prims/jvmtiEventController.cpp index df14047e700..32d691a5793 100644 --- a/src/hotspot/share/prims/jvmtiEventController.cpp +++ b/src/hotspot/share/prims/jvmtiEventController.cpp @@ -598,7 +598,7 @@ JvmtiEventControllerPrivate::recompute_thread_enabled(JvmtiThreadState *state) { } // compute interp_only mode bool should_be_interp = (any_env_enabled & INTERP_EVENT_BITS) != 0 || has_frame_pops; - bool is_now_interp = state->is_interp_only_mode(); + bool is_now_interp = state->is_interp_only_mode() || state->is_pending_interp_only_mode(); if (should_be_interp != is_now_interp) { if (should_be_interp) { diff --git a/src/hotspot/share/runtime/continuation.cpp b/src/hotspot/share/runtime/continuation.cpp index fd9e4615498..d21e87ab746 100644 --- a/src/hotspot/share/runtime/continuation.cpp +++ b/src/hotspot/share/runtime/continuation.cpp @@ -60,14 +60,14 @@ JVM_END #if INCLUDE_JVMTI class JvmtiUnmountBeginMark : public StackObj { Handle _vthread; - JavaThread* _target; + JavaThread* _current; freeze_result _result; bool _failed; public: JvmtiUnmountBeginMark(JavaThread* t) : - _vthread(t, t->vthread()), _target(t), _result(freeze_pinned_native), _failed(false) { - assert(!_target->is_in_VTMS_transition(), "must be"); + _vthread(t, t->vthread()), _current(t), _result(freeze_pinned_native), _failed(false) { + assert(!_current->is_in_VTMS_transition(), "must be"); if (JvmtiVTMSTransitionDisabler::VTMS_notify_jvmti_events()) { JvmtiVTMSTransitionDisabler::VTMS_vthread_unmount((jthread)_vthread.raw_value(), true); @@ -75,26 +75,26 @@ class JvmtiUnmountBeginMark : public StackObj { // Don't preempt if there is a pending popframe or earlyret operation. This can // be installed in start_VTMS_transition() so we need to check it here. if (JvmtiExport::can_pop_frame() || JvmtiExport::can_force_early_return()) { - JvmtiThreadState* state = _target->jvmti_thread_state(); - if (_target->has_pending_popframe() || (state != nullptr && state->is_earlyret_pending())) { + JvmtiThreadState* state = _current->jvmti_thread_state(); + if (_current->has_pending_popframe() || (state != nullptr && state->is_earlyret_pending())) { _failed = true; } } // Don't preempt in case there is an async exception installed since // we would incorrectly throw it during the unmount logic in the carrier. - if (_target->has_async_exception_condition()) { + if (_current->has_async_exception_condition()) { _failed = true; } } else { - _target->set_is_in_VTMS_transition(true); + _current->set_is_in_VTMS_transition(true); java_lang_Thread::set_is_in_VTMS_transition(_vthread(), true); } } ~JvmtiUnmountBeginMark() { - assert(!_target->is_suspended(), "must be"); + assert(!_current->is_suspended(), "must be"); - assert(_target->is_in_VTMS_transition(), "must be"); + assert(_current->is_in_VTMS_transition(), "must be"); assert(java_lang_Thread::is_in_VTMS_transition(_vthread()), "must be"); // Read it again since for late binding agents the flag could have @@ -106,7 +106,7 @@ class JvmtiUnmountBeginMark : public StackObj { if (jvmti_present) { JvmtiVTMSTransitionDisabler::VTMS_vthread_mount((jthread)_vthread.raw_value(), false); } else { - _target->set_is_in_VTMS_transition(false); + _current->set_is_in_VTMS_transition(false); java_lang_Thread::set_is_in_VTMS_transition(_vthread(), false); } } @@ -115,51 +115,59 @@ class JvmtiUnmountBeginMark : public StackObj { bool failed() { return _failed; } }; -static bool is_vthread_safe_to_preempt_for_jvmti(JavaThread* target) { - if (target->is_in_VTMS_transition()) { - // We caught target at the end of a mount transition. +static bool is_vthread_safe_to_preempt_for_jvmti(JavaThread* current) { + if (current->is_in_VTMS_transition()) { + // We are at the end of a mount transition. return false; } return true; } #endif // INCLUDE_JVMTI -static bool is_vthread_safe_to_preempt(JavaThread* target, oop vthread) { +static bool is_vthread_safe_to_preempt(JavaThread* current, oop vthread) { assert(java_lang_VirtualThread::is_instance(vthread), ""); if (java_lang_VirtualThread::state(vthread) != java_lang_VirtualThread::RUNNING) { // inside transition return false; } - return JVMTI_ONLY(is_vthread_safe_to_preempt_for_jvmti(target)) NOT_JVMTI(true); + return JVMTI_ONLY(is_vthread_safe_to_preempt_for_jvmti(current)) NOT_JVMTI(true); } typedef freeze_result (*FreezeContFnT)(JavaThread*, intptr_t*); -static void verify_preempt_preconditions(JavaThread* target, oop continuation) { - assert(target == JavaThread::current(), "no support for external preemption"); - assert(target->has_last_Java_frame(), ""); - assert(!target->preempting(), ""); - assert(target->last_continuation() != nullptr, ""); - assert(target->last_continuation()->cont_oop(target) == continuation, ""); +static void verify_preempt_preconditions(JavaThread* current, oop continuation) { + assert(current == JavaThread::current(), "no support for external preemption"); + assert(current->has_last_Java_frame(), ""); + assert(!current->preempting(), ""); + assert(current->last_continuation() != nullptr, ""); + assert(current->last_continuation()->cont_oop(current) == continuation, ""); assert(Continuation::continuation_scope(continuation) == java_lang_VirtualThread::vthread_scope(), ""); - assert(!target->has_pending_exception(), ""); + assert(!current->has_pending_exception(), ""); } -freeze_result Continuation::try_preempt(JavaThread* target, oop continuation) { - verify_preempt_preconditions(target, continuation); +freeze_result Continuation::try_preempt(JavaThread* current, oop continuation) { + verify_preempt_preconditions(current, continuation); if (LockingMode == LM_LEGACY) { return freeze_unsupported; } - if (!is_vthread_safe_to_preempt(target, target->vthread())) { + if (!is_vthread_safe_to_preempt(current, current->vthread())) { return freeze_pinned_native; } - JVMTI_ONLY(JvmtiUnmountBeginMark jubm(target);) + JVMTI_ONLY(JvmtiUnmountBeginMark jubm(current);) JVMTI_ONLY(if (jubm.failed()) return freeze_pinned_native;) - freeze_result res = CAST_TO_FN_PTR(FreezeContFnT, freeze_preempt_entry())(target, target->last_Java_sp()); + freeze_result res = CAST_TO_FN_PTR(FreezeContFnT, freeze_preempt_entry())(current, current->last_Java_sp()); log_trace(continuations, preempt)("try_preempt: %d", res); JVMTI_ONLY(jubm.set_result(res);) + + if (current->has_pending_exception()) { + assert(res == freeze_exception, "expecting an exception result from freeze"); + // We don't want to throw exceptions, especially when returning + // from monitorenter since the compiler does not expect one. We + // just ignore the exception and pin the vthread to the carrier. + current->clear_pending_exception(); + } return res; } diff --git a/src/hotspot/share/runtime/continuationFreezeThaw.cpp b/src/hotspot/share/runtime/continuationFreezeThaw.cpp index a6c8e64e55e..ccbcaf452af 100644 --- a/src/hotspot/share/runtime/continuationFreezeThaw.cpp +++ b/src/hotspot/share/runtime/continuationFreezeThaw.cpp @@ -2603,6 +2603,7 @@ void ThawBase::recurse_thaw_compiled_frame(const frame& hf, frame& caller, int n || (stub_caller && f.cb()->as_nmethod()->is_marked_for_deoptimization())) { // The caller of the safepoint stub when the continuation is preempted is not at a call instruction, and so // cannot rely on nmethod patching for deopt. + assert(_thread->is_interp_only_mode() || stub_caller, "expected a stub-caller"); log_develop_trace(continuations)("Deoptimizing thawed frame"); DEBUG_ONLY(ContinuationHelper::Frame::patch_pc(f, nullptr)); diff --git a/src/hotspot/share/runtime/synchronizer.cpp b/src/hotspot/share/runtime/synchronizer.cpp index 941309ca2ac..fdce6d21531 100644 --- a/src/hotspot/share/runtime/synchronizer.cpp +++ b/src/hotspot/share/runtime/synchronizer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1264,36 +1264,49 @@ static bool monitors_used_above_threshold(MonitorList* list) { if (MonitorUsedDeflationThreshold == 0) { // disabled case is easy return false; } - // Start with ceiling based on a per-thread estimate: - size_t ceiling = ObjectSynchronizer::in_use_list_ceiling(); - size_t old_ceiling = ceiling; - if (ceiling < list->max()) { - // The max used by the system has exceeded the ceiling so use that: - ceiling = list->max(); - } size_t monitors_used = list->count(); if (monitors_used == 0) { // empty list is easy return false; } - if (NoAsyncDeflationProgressMax != 0 && - _no_progress_cnt >= NoAsyncDeflationProgressMax) { - double remainder = (100.0 - MonitorUsedDeflationThreshold) / 100.0; - size_t new_ceiling = ceiling + (size_t)((double)ceiling * remainder) + 1; - ObjectSynchronizer::set_in_use_list_ceiling(new_ceiling); - log_info(monitorinflation)("Too many deflations without progress; " - "bumping in_use_list_ceiling from " SIZE_FORMAT - " to " SIZE_FORMAT, old_ceiling, new_ceiling); - _no_progress_cnt = 0; - ceiling = new_ceiling; - } + size_t old_ceiling = ObjectSynchronizer::in_use_list_ceiling(); + // Make sure that we use a ceiling value that is not lower than + // previous, not lower than the recorded max used by the system, and + // not lower than the current number of monitors in use (which can + // race ahead of max). The result is guaranteed > 0. + size_t ceiling = MAX3(old_ceiling, list->max(), monitors_used); // Check if our monitor usage is above the threshold: size_t monitor_usage = (monitors_used * 100LL) / ceiling; if (int(monitor_usage) > MonitorUsedDeflationThreshold) { + // Deflate monitors if over the threshold percentage, unless no + // progress on previous deflations. + bool is_above_threshold = true; + + // Check if it's time to adjust the in_use_list_ceiling up, due + // to too many async deflation attempts without any progress. + if (NoAsyncDeflationProgressMax != 0 && + _no_progress_cnt >= NoAsyncDeflationProgressMax) { + double remainder = (100.0 - MonitorUsedDeflationThreshold) / 100.0; + size_t delta = (size_t)(ceiling * remainder) + 1; + size_t new_ceiling = (ceiling > SIZE_MAX - delta) + ? SIZE_MAX // Overflow, let's clamp new_ceiling. + : ceiling + delta; + + ObjectSynchronizer::set_in_use_list_ceiling(new_ceiling); + log_info(monitorinflation)("Too many deflations without progress; " + "bumping in_use_list_ceiling from " SIZE_FORMAT + " to " SIZE_FORMAT, old_ceiling, new_ceiling); + _no_progress_cnt = 0; + ceiling = new_ceiling; + + // Check if our monitor usage is still above the threshold: + monitor_usage = (monitors_used * 100LL) / ceiling; + is_above_threshold = int(monitor_usage) > MonitorUsedDeflationThreshold; + } log_info(monitorinflation)("monitors_used=" SIZE_FORMAT ", ceiling=" SIZE_FORMAT ", monitor_usage=" SIZE_FORMAT ", threshold=%d", monitors_used, ceiling, monitor_usage, MonitorUsedDeflationThreshold); - return true; + return is_above_threshold; } return false; diff --git a/src/hotspot/share/services/heapDumper.cpp b/src/hotspot/share/services/heapDumper.cpp index 91bcce382f0..dfe612c7bf3 100644 --- a/src/hotspot/share/services/heapDumper.cpp +++ b/src/hotspot/share/services/heapDumper.cpp @@ -2349,11 +2349,10 @@ void VM_HeapDumper::dump_threads(AbstractDumpWriter* writer) { } bool VM_HeapDumper::doit_prologue() { - if (_gc_before_heap_dump && UseZGC) { - // ZGC cannot perform a synchronous GC cycle from within the VM thread. - // So ZCollectedHeap::collect_as_vm_thread() is a noop. To respect the - // _gc_before_heap_dump flag a synchronous GC cycle is performed from - // the caller thread in the prologue. + if (_gc_before_heap_dump && (UseZGC || UseShenandoahGC)) { + // ZGC and Shenandoah cannot perform a synchronous GC cycle from within the VM thread. + // So collect_as_vm_thread() is a noop. To respect the _gc_before_heap_dump flag a + // synchronous GC cycle is performed from the caller thread in the prologue. Universe::heap()->collect(GCCause::_heap_dump); } return VM_GC_Operation::doit_prologue(); diff --git a/src/java.base/share/classes/com/sun/crypto/provider/HKDFKeyDerivation.java b/src/java.base/share/classes/com/sun/crypto/provider/HKDFKeyDerivation.java index a9988bbc115..9b4cf557598 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/HKDFKeyDerivation.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/HKDFKeyDerivation.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -180,8 +180,8 @@ protected byte[] engineDeriveData(AlgorithmParameterSpec derivationSpec) } else if (derivationSpec instanceof HKDFParameterSpec.Expand anExpand) { // set this value in the "if" if ((pseudoRandomKey = anExpand.prk().getEncoded()) == null) { - throw new AssertionError( - "PRK is required for HKDFParameterSpec.Expand"); + throw new InvalidAlgorithmParameterException( + "Cannot retrieve PRK for HKDFParameterSpec.Expand"); } // set this value in the "if" if ((info = anExpand.info()) == null) { @@ -411,4 +411,4 @@ public HKDFSHA512(KDFParameters kdfParameters) } } -} \ No newline at end of file +} diff --git a/src/java.base/share/classes/java/lang/Double.java b/src/java.base/share/classes/java/lang/Double.java index 8f7b6c6aa42..54be998cac5 100644 --- a/src/java.base/share/classes/java/lang/Double.java +++ b/src/java.base/share/classes/java/lang/Double.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -349,8 +349,8 @@ * @jls 15.21.1 Numerical Equality Operators == and != * @jls 15.20.1 Numerical Comparison Operators {@code <}, {@code <=}, {@code >}, and {@code >=} * - * @see - * IEEE Standard for Floating-Point Arithmetic + * @spec https://standards.ieee.org/ieee/754/6210/ + * IEEE Standard for Floating-Point Arithmetic * * @author Lee Boynton * @author Arthur van Hoff diff --git a/src/java.base/share/classes/java/lang/Float.java b/src/java.base/share/classes/java/lang/Float.java index 85b20e6a2e1..746d90db81e 100644 --- a/src/java.base/share/classes/java/lang/Float.java +++ b/src/java.base/share/classes/java/lang/Float.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -67,8 +67,8 @@ * decimal conversion issues} in {@code java.lang.Double} is also * applicable to {@code float} values. * - * @see - * IEEE Standard for Floating-Point Arithmetic + * @spec https://standards.ieee.org/ieee/754/6210/ + * IEEE Standard for Floating-Point Arithmetic * * @author Lee Boynton * @author Arthur van Hoff diff --git a/src/java.base/share/classes/java/lang/Math.java b/src/java.base/share/classes/java/lang/Math.java index 6b576c88b47..6403524a49e 100644 --- a/src/java.base/share/classes/java/lang/Math.java +++ b/src/java.base/share/classes/java/lang/Math.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -120,8 +120,8 @@ * implementation condition than required for most of the methods in * question that are also included in this class. * - * @see - * IEEE Standard for Floating-Point Arithmetic + * @spec https://standards.ieee.org/ieee/754/6210/ + * IEEE Standard for Floating-Point Arithmetic * * @since 1.0 */ diff --git a/src/java.base/share/classes/java/lang/StrictMath.java b/src/java.base/share/classes/java/lang/StrictMath.java index 6db10113c8a..e3b51ed752c 100644 --- a/src/java.base/share/classes/java/lang/StrictMath.java +++ b/src/java.base/share/classes/java/lang/StrictMath.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -98,8 +98,8 @@ * href="Math.html#Ieee754RecommendedOps">relate to the IEEE 754 * recommended operations. * - * @see - * IEEE Standard for Floating-Point Arithmetic + * @spec https://standards.ieee.org/ieee/754/6210/ + * IEEE Standard for Floating-Point Arithmetic * * @author Joseph D. Darcy * @since 1.3 diff --git a/src/java.base/share/classes/java/lang/classfile/BootstrapMethodEntry.java b/src/java.base/share/classes/java/lang/classfile/BootstrapMethodEntry.java index 1608e77bee6..ab246a8653b 100644 --- a/src/java.base/share/classes/java/lang/classfile/BootstrapMethodEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/BootstrapMethodEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,9 @@ package java.lang.classfile; +import java.lang.classfile.attribute.BootstrapMethodsAttribute; import java.lang.classfile.constantpool.ConstantPool; +import java.lang.classfile.constantpool.ConstantPoolBuilder; import java.lang.classfile.constantpool.LoadableConstantEntry; import java.lang.classfile.constantpool.MethodHandleEntry; import java.util.List; @@ -34,10 +36,20 @@ /** * Models an entry in the bootstrap method table. The bootstrap method table - * is stored in the {@code BootstrapMethods} attribute, but is modeled by - * the {@link ConstantPool}, since the bootstrap method table is logically - * part of the constant pool. + * is stored in the {@link BootstrapMethodsAttribute BootstrapMethods} + * attribute, but is modeled by the {@link ConstantPool}, since the bootstrap + * method table is logically part of the constant pool. + *

+ * A bootstrap method entry is composite: + * {@snippet lang=text : + * // @link substring="BootstrapMethodEntry" target="ConstantPoolBuilder#bsmEntry(MethodHandleEntry, List)" : + * BootstrapMethodEntry( + * MethodHandleEntry bootstrapMethod, // @link substring="bootstrapMethod" target="#bootstrapMethod" + * List arguments // @link substring="arguments" target="#arguments()" + * ) + * } * + * @see ConstantPoolBuilder#bsmEntry ConstantPoolBuilder::bsmEntry * @since 24 */ public sealed interface BootstrapMethodEntry @@ -45,11 +57,19 @@ public sealed interface BootstrapMethodEntry /** * {@return the constant pool associated with this entry} + * + * @apiNote + * Given a {@link ConstantPoolBuilder} {@code builder} and a {@code + * BootstrapMethodEntry} {@code entry}, use {@link + * ConstantPoolBuilder#canWriteDirect + * builder.canWriteDirect(entry.constantPool())} instead of object equality + * of the constant pool to determine if an entry is compatible. */ ConstantPool constantPool(); /** - * {@return the index into the bootstrap method table corresponding to this entry} + * {@return the index into the bootstrap method table corresponding to this + * entry} */ int bsmIndex(); diff --git a/src/java.base/share/classes/java/lang/classfile/ClassFile.java b/src/java.base/share/classes/java/lang/classfile/ClassFile.java index db293f41588..61685a5c1e0 100644 --- a/src/java.base/share/classes/java/lang/classfile/ClassFile.java +++ b/src/java.base/share/classes/java/lang/classfile/ClassFile.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,6 +32,8 @@ import java.lang.classfile.constantpool.ClassEntry; import java.lang.classfile.constantpool.ConstantPoolBuilder; import java.lang.classfile.constantpool.Utf8Entry; +import java.lang.classfile.instruction.BranchInstruction; +import java.lang.classfile.instruction.DiscontinuedInstruction; import java.lang.classfile.instruction.ExceptionCatch; import java.lang.constant.ClassDesc; import java.lang.reflect.AccessFlag; @@ -138,21 +140,56 @@ static ClassHierarchyResolverOption of(ClassHierarchyResolver classHierarchyReso /** * Option describing whether to preserve the original constant pool when - * transforming a classfile. Reusing the constant pool enables significant - * optimizations in processing time and minimizes differences between the - * original and transformed classfile, but may result in a bigger classfile - * when a classfile is significantly transformed. - * Default is {@code SHARED_POOL} to preserve the original constant - * pool. + * transforming a {@code class} file. Reusing the constant pool enables + * significant optimizations in processing time and minimizes differences + * between the original and transformed {@code class} files, but may result + * in a bigger transformed {@code class} file when many elements of the + * original {@code class} file are dropped and many original constant + * pool entries become unused. Default is {@link #SHARED_POOL} to preserve + * the original constant pool. * + * @see ConstantPoolBuilder + * @see #build(ClassEntry, ConstantPoolBuilder, Consumer) + * @see #transformClass(ClassModel, ClassTransform) * @since 24 */ enum ConstantPoolSharingOption implements Option { - /** Preserves the original constant pool when transforming classfile */ + /** + * Preserves the original constant pool when transforming the {@code + * class} file. + *

+ * These two transformations below are equivalent: + * {@snippet lang=java : + * ClassModel originalClass = null; // @replace substring=null; replacement=... + * ClassDesc resultClassName = null; // @replace substring=null; replacement=... + * ClassTransform classTransform = null; // @replace substring=null; replacement=... + * var resultOne = ClassFile.of(ConstantPoolSharingOption.SHARED_POOL) + * .transformClass(originalClass, resultClassName, classTransform); + * var resultTwo = ClassFile.of().build(resultClassName, ConstantPoolBuilder.of(originalClass), + * clb -> clb.transform(originalClass, classTransform)); + * } + * + * @see ConstantPoolBuilder#of(ClassModel) ConstantPoolBuilder::of(ClassModel) + */ SHARED_POOL, - /** Creates a new constant pool when transforming classfile */ + /** + * Creates a new constant pool when transforming the {@code class} file. + *

+ * These two transformations below are equivalent: + * {@snippet lang=java : + * ClassModel originalClass = null; // @replace substring=null; replacement=... + * ClassDesc resultClassName = null; // @replace substring=null; replacement=... + * ClassTransform classTransform = null; // @replace substring=null; replacement=... + * var resultOne = ClassFile.of(ConstantPoolSharingOption.NEW_POOL) + * .transformClass(originalClass, resultClassName, classTransform); + * var resultTwo = ClassFile.of().build(resultClassName, ConstantPoolBuilder.of(), + * clb -> clb.transform(originalClass, classTransform)); + * } + * + * @see ConstantPoolBuilder#of() ConstantPoolBuilder::of() + */ NEW_POOL } @@ -230,17 +267,35 @@ enum LineNumbersOption implements Option { /** * Option describing whether to automatically rewrite short jumps to * long when necessary. - * Default is {@code FIX_SHORT_JUMPS} to automatically rewrite jump + * Default is {@link #FIX_SHORT_JUMPS} to automatically rewrite jump * instructions. + *

+ * Due to physical restrictions, some types of instructions cannot encode + * certain jump targets with bci offsets less than -32768 or greater than + * 32767, as they use a {@code s2} to encode such an offset. (The maximum + * length of the {@code code} array is 65535.) These types of instructions + * are called "short jumps". * + * @see BranchInstruction + * @see DiscontinuedInstruction.JsrInstruction * @since 24 */ enum ShortJumpsOption implements Option { - /** Automatically convert short jumps to long when necessary */ + /** + * Automatically convert short jumps to long when necessary. + *

+ * For an invalid instruction model, a {@link CodeBuilder} may generate + * another or a few other instructions to accomplish the same effect. + */ FIX_SHORT_JUMPS, - /** Fail if short jump overflows */ + /** + * Fail with an {@link IllegalArgumentException} if short jump overflows. + *

+ * This is useful to ensure the physical accuracy of a generated {@code + * class} file. + */ FAIL_ON_SHORT_JUMPS } diff --git a/src/java.base/share/classes/java/lang/classfile/CodeBuilder.java b/src/java.base/share/classes/java/lang/classfile/CodeBuilder.java index 1a074c1554a..3cbcb893cb1 100644 --- a/src/java.base/share/classes/java/lang/classfile/CodeBuilder.java +++ b/src/java.base/share/classes/java/lang/classfile/CodeBuilder.java @@ -51,7 +51,7 @@ * #with(ClassFileElement)} or concretely by calling the various {@code withXxx} * methods. * - *

Instruction Factories

+ *

Instruction Factories

* {@code CodeBuilder} provides convenience methods to create instructions (See * JVMS {@jvms 6.5} Instructions) by their mnemonic, taking necessary operands. *
    diff --git a/src/java.base/share/classes/java/lang/classfile/CompoundElement.java b/src/java.base/share/classes/java/lang/classfile/CompoundElement.java index 38d149623e1..d9f9fe1e5f9 100644 --- a/src/java.base/share/classes/java/lang/classfile/CompoundElement.java +++ b/src/java.base/share/classes/java/lang/classfile/CompoundElement.java @@ -34,6 +34,8 @@ import java.util.stream.Stream; import java.util.stream.StreamSupport; +import jdk.internal.classfile.components.ClassPrinter; + /** * A {@link ClassFileElement} that has complex structure defined in terms of * other classfile elements, such as a method, field, method body, or entire @@ -92,4 +94,14 @@ public void accept(E e) { return Collections.unmodifiableList(list); } + /** + * {@return a text representation of the compound element and its contents for debugging purposes} + * + * The format, structure and exact contents of the returned string are not specified and may change at any time in the future. + */ + default String toDebugString() { + StringBuilder text = new StringBuilder(); + ClassPrinter.toYaml(this, ClassPrinter.Verbosity.TRACE_ALL, text::append); + return text.toString(); + } } diff --git a/src/java.base/share/classes/java/lang/classfile/Instruction.java b/src/java.base/share/classes/java/lang/classfile/Instruction.java index 2fe0ec5a588..199aa6447a1 100644 --- a/src/java.base/share/classes/java/lang/classfile/Instruction.java +++ b/src/java.base/share/classes/java/lang/classfile/Instruction.java @@ -25,13 +25,20 @@ package java.lang.classfile; +import java.lang.classfile.attribute.CodeAttribute; import java.lang.classfile.instruction.*; import jdk.internal.classfile.impl.AbstractInstruction; /** - * Models an executable instruction in a method body. + * Models an executable instruction in the {@code code} array of the {@link + * CodeAttribute Code} attribute of a method. + *

    + * The {@link #opcode() opcode} identifies the operation of an instruction. + * Each {@linkplain Opcode#kind() kind} of opcode has its own modeling interface + * for instructions. * + * @sealedGraph * @since 24 */ public sealed interface Instruction extends CodeElement @@ -46,12 +53,14 @@ public sealed interface Instruction extends CodeElement ThrowInstruction, TypeCheckInstruction, AbstractInstruction { /** - * {@return the opcode of this instruction} + * {@return the operation of this instruction} */ Opcode opcode(); /** * {@return the size in bytes of this instruction} + * This value is equal to {@link Opcode#sizeIfFixed() + * opcode().sizeIfFixed()} if it is not {@code -1}. */ int sizeInBytes(); } diff --git a/src/java.base/share/classes/java/lang/classfile/Label.java b/src/java.base/share/classes/java/lang/classfile/Label.java index e958e116084..653c410728c 100644 --- a/src/java.base/share/classes/java/lang/classfile/Label.java +++ b/src/java.base/share/classes/java/lang/classfile/Label.java @@ -24,21 +24,60 @@ */ package java.lang.classfile; +import java.lang.classfile.attribute.CodeAttribute; +import java.lang.classfile.instruction.LabelTarget; +import java.util.ListIterator; + import jdk.internal.classfile.impl.LabelImpl; /** * A marker for a position within the instructions of a method body. The - * association between a label's identity and the position it represents is - * managed by the entity managing the method body (a {@link CodeModel} or {@link - * CodeBuilder}), not the label itself; this allows the same label to have a - * meaning both in an existing method (as managed by a {@linkplain CodeModel}) - * and in the transformation of that method (as managed by a {@linkplain - * CodeBuilder}), while corresponding to different positions in each. When - * traversing the elements of a {@linkplain CodeModel}, {@linkplain Label} - * markers will be delivered at the position to which they correspond. A label - * can be bound to the current position within a {@linkplain CodeBuilder} via - * {@link CodeBuilder#labelBinding(Label)} or {@link CodeBuilder#with(ClassFileElement)}. + * position is a cursor position in the list of instructions, similar to that + * of a {@link ListIterator}. + * + *

    Reading Labels

    + * Labels read from {@code class} files represent positions in the {@code code} + * array of a {@link CodeAttribute Code} attribute. It is associated with a + * {@index bci} (bytecode index), also known as {@index pc} + * (program counter), the index into the {@code code} array; the actual cursor + * position is immediately before the given index, so a label at the beginning + * of the instructions has bci {@code 0}, and a label at the end of the + * instructions has bci {@link CodeAttribute#codeLength codeLength() + 1}. The + * bci can be inspected through {@link CodeAttribute#labelToBci + * CodeAttribute::labelToBci}. + *

    + * In generic {@link CodeModel}s, a label may not have a bci value; the position + * of a label can be found by searching for the corresponding {@link LabelTarget} + * within that model. + * + *

    Writing Labels

    + * Many models in {@link java.lang.classfile} refer to labels. To write a + * label, a label must be obtained, it must be bound to a {@link CodeBuilder}. + *

    + * To obtain a label: + *

      + *
    • Use a label read from other models. + *
    • Use pre-defined labels from a {@link CodeBuilder}, such as {@link + * CodeBuilder#startLabel() CodeBuilder::startLabel}, {@link CodeBuilder#endLabel + * CodeBuilder::endLabel}, or {@link CodeBuilder.BlockCodeBuilder#breakLabel + * BlockCodeBuilder::breakLabel}. They are already bound. + *
    • Create labels with {@link CodeBuilder#newLabel CodeBuilder::newLabel} or + * {@link CodeBuilder#newBoundLabel CodeBuilder::newBoundLabel}. + *
    + *

    + * A label must be bound exactly once in the {@code CodeBuilder} where it is + * used; otherwise, writing fails. To bind an unbound label: + *

      + *
    • Send a read {@link LabelTarget} to a {@code CodeBuilder}. + *
    • Use {@link CodeBuilder#labelBinding CodeBuilder::labelBinding}. + *
    + * Note that a label read from another model is not automatically bound in a + * {@code CodeBuilder}; they are separate entities and the label is bound to + * different positions in them. * + * @see CodeAttribute#labelToBci CodeAttribute::labelToBci + * @see CodeBuilder#newLabel CodeBuilder::newLabel + * @see CodeBuilder#labelBinding CodeBuilder::labelBinding * @since 24 */ public sealed interface Label diff --git a/src/java.base/share/classes/java/lang/classfile/Opcode.java b/src/java.base/share/classes/java/lang/classfile/Opcode.java index 4d333400001..a3b0a370763 100644 --- a/src/java.base/share/classes/java/lang/classfile/Opcode.java +++ b/src/java.base/share/classes/java/lang/classfile/Opcode.java @@ -24,684 +24,1849 @@ */ package java.lang.classfile; +import java.lang.classfile.instruction.*; + import jdk.internal.classfile.impl.RawBytecodeHelper; /** * Describes the opcodes of the JVM instruction set, as described in JVMS {@jvms 6.5}. - * As well as a number of pseudo-instructions that may be encountered when - * traversing the instructions of a method. + * This includes a few pseudo-opcodes modified by {@link #isWide() wide}. + *

    + * An opcode describes the operation of an instruction. + * + * @apiNote + * The enum constants are named after the opcodes' mnemonics in uppercase. + * Wide pseudo-opcodes are named with the original opcodes' mnemonic plus + * a {@code _W} suffix. However, {@link #LDC_W ldc_w}, {@link #LDC2_W ldc2_w}, + * {@link #GOTO_W goto_w}, and {@link #JSR_W jsr_w} are legitimate opcodes + * instead of wide pseudo-opcodes. * * @see Instruction - * @see PseudoInstruction * * @since 24 */ public enum Opcode { - /** Do nothing */ + /** + * Do nothing. + * + * @jvms 6.5.nop nop + * @see Kind#NOP + */ NOP(RawBytecodeHelper.NOP, 1, Kind.NOP), - /** Push null */ + /** + * Push {@code null}. + * + * @jvms 6.5.aconst_null aconst_null + * @see ConstantInstruction.IntrinsicConstantInstruction + * @see Kind#CONSTANT + */ ACONST_NULL(RawBytecodeHelper.ACONST_NULL, 1, Kind.CONSTANT), - /** Push int constant -1 */ + /** + * Push {@link TypeKind#INT int} constant {@code -1}. + * + * @jvms 6.5.iconst_i iconst_<i> + * @see ConstantInstruction.IntrinsicConstantInstruction + * @see Kind#CONSTANT + */ ICONST_M1(RawBytecodeHelper.ICONST_M1, 1, Kind.CONSTANT), - /** Push int constant 0 */ + /** + * Push {@link TypeKind#INT int} constant {@code 0}. + * + * @jvms 6.5.iconst_i iconst_<i> + * @see ConstantInstruction.IntrinsicConstantInstruction + * @see Kind#CONSTANT + */ ICONST_0(RawBytecodeHelper.ICONST_0, 1, Kind.CONSTANT), - /** Push int constant 1 */ + /** + * Push {@link TypeKind#INT int} constant {@code 1}. + * + * @jvms 6.5.iconst_i iconst_<i> + * @see ConstantInstruction.IntrinsicConstantInstruction + * @see Kind#CONSTANT + */ ICONST_1(RawBytecodeHelper.ICONST_1, 1, Kind.CONSTANT), - /** Push int constant 2 */ + /** + * Push {@link TypeKind#INT int} constant {@code 2}. + * + * @jvms 6.5.iconst_i iconst_<i> + * @see ConstantInstruction.IntrinsicConstantInstruction + * @see Kind#CONSTANT + */ ICONST_2(RawBytecodeHelper.ICONST_2, 1, Kind.CONSTANT), - /** Push int constant 3 */ + /** + * Push {@link TypeKind#INT int} constant {@code 3}. + * + * @jvms 6.5.iconst_i iconst_<i> + * @see ConstantInstruction.IntrinsicConstantInstruction + * @see Kind#CONSTANT + */ ICONST_3(RawBytecodeHelper.ICONST_3, 1, Kind.CONSTANT), - /** Push int constant 4 */ + /** + * Push {@link TypeKind#INT int} constant {@code 4}. + * + * @jvms 6.5.iconst_i iconst_<i> + * @see ConstantInstruction.IntrinsicConstantInstruction + * @see Kind#CONSTANT + */ ICONST_4(RawBytecodeHelper.ICONST_4, 1, Kind.CONSTANT), - /** Push int constant 5 */ + /** + * Push {@link TypeKind#INT int} constant {@code 5}. + * + * @jvms 6.5.iconst_i iconst_<i> + * @see ConstantInstruction.IntrinsicConstantInstruction + * @see Kind#CONSTANT + */ ICONST_5(RawBytecodeHelper.ICONST_5, 1, Kind.CONSTANT), - /** Push long constant 0 */ + /** + * Push {@link TypeKind#LONG long} constant {@code 0L}. + * + * @jvms 6.5.lconst_l lconst_<l> + * @see ConstantInstruction.IntrinsicConstantInstruction + * @see Kind#CONSTANT + */ LCONST_0(RawBytecodeHelper.LCONST_0, 1, Kind.CONSTANT), - /** Push long constant 1 */ + /** + * Push {@link TypeKind#LONG long} constant {@code 1L}. + * + * @jvms 6.5.lconst_l lconst_<l> + * @see ConstantInstruction.IntrinsicConstantInstruction + * @see Kind#CONSTANT + */ LCONST_1(RawBytecodeHelper.LCONST_1, 1, Kind.CONSTANT), - /** Push float constant 0 */ + /** + * Push {@link TypeKind#FLOAT float} constant {@code 0.0F}. + * + * @jvms 6.5.fconst_f fconst_<f> + * @see ConstantInstruction.IntrinsicConstantInstruction + * @see Kind#CONSTANT + */ FCONST_0(RawBytecodeHelper.FCONST_0, 1, Kind.CONSTANT), - /** Push float constant 1 */ + /** + * Push {@link TypeKind#FLOAT float} constant {@code 1.0F}. + * + * @jvms 6.5.fconst_f fconst_<f> + * @see ConstantInstruction.IntrinsicConstantInstruction + * @see Kind#CONSTANT + */ FCONST_1(RawBytecodeHelper.FCONST_1, 1, Kind.CONSTANT), - /** Push float constant 2 */ + /** + * Push {@link TypeKind#FLOAT float} constant {@code 2.0F}. + * + * @jvms 6.5.fconst_f fconst_<f> + * @see ConstantInstruction.IntrinsicConstantInstruction + * @see Kind#CONSTANT + */ FCONST_2(RawBytecodeHelper.FCONST_2, 1, Kind.CONSTANT), - /** Push double constant 0 */ + /** + * Push {@link TypeKind#DOUBLE double} constant {@code 0.0D}. + * + * @jvms 6.5.dconst_d dconst_<d> + * @see ConstantInstruction.IntrinsicConstantInstruction + * @see Kind#CONSTANT + */ DCONST_0(RawBytecodeHelper.DCONST_0, 1, Kind.CONSTANT), - /** Push double constant 1 */ + /** + * Push {@link TypeKind#DOUBLE double} constant {@code 1.0D}. + * + * @jvms 6.5.dconst_d dconst_<d> + * @see ConstantInstruction.IntrinsicConstantInstruction + * @see Kind#CONSTANT + */ DCONST_1(RawBytecodeHelper.DCONST_1, 1, Kind.CONSTANT), - /** Push byte */ + /** + * Push {@link TypeKind#INT int} value from sign-extension of immediate + * {@link TypeKind#BYTE byte} value. + * + * @jvms 6.5.bipush bipush + * @see ConstantInstruction.ArgumentConstantInstruction + * @see Kind#CONSTANT + */ BIPUSH(RawBytecodeHelper.BIPUSH, 2, Kind.CONSTANT), - /** Push short */ + /** + * Push {@link TypeKind#INT int} value from sign-extension of immediate + * {@link TypeKind#SHORT short} value. + * + * @jvms 6.5.sipush sipush + * @see ConstantInstruction.ArgumentConstantInstruction + * @see Kind#CONSTANT + */ SIPUSH(RawBytecodeHelper.SIPUSH, 3, Kind.CONSTANT), - /** Push item from run-time constant pool */ + /** + * Push item from run-time constant pool. + * + * @jvms 6.5.ldc ldc + * @see ConstantInstruction.LoadConstantInstruction + * @see Kind#CONSTANT + */ LDC(RawBytecodeHelper.LDC, 2, Kind.CONSTANT), - /** Push item from run-time constant pool (wide index) */ + /** + * Push item from run-time constant pool (wide index). + * + * @jvms 6.5.ldc_w ldc_w + * @see ConstantInstruction.LoadConstantInstruction + * @see Kind#CONSTANT + */ LDC_W(RawBytecodeHelper.LDC_W, 3, Kind.CONSTANT), - /** Push long or double from run-time constant pool (wide index) */ + /** + * Push {@link TypeKind#LONG long} or {@link TypeKind#DOUBLE double} + * from run-time constant pool (wide index). + * + * @jvms 6.5.ldc2_w ldc2_w + * @see ConstantInstruction.LoadConstantInstruction + * @see Kind#CONSTANT + */ LDC2_W(RawBytecodeHelper.LDC2_W, 3, Kind.CONSTANT), - /** Load int from local variable */ + /** + * Load {@link TypeKind#INT int} from local variable. + * + * @jvms 6.5.iload iload + * @see Kind#LOAD + */ ILOAD(RawBytecodeHelper.ILOAD, 2, Kind.LOAD), - /** Load long from local variable */ + /** + * Load {@link TypeKind#LONG long} from local variable. + * + * @jvms 6.5.lload lload + * @see Kind#LOAD + */ LLOAD(RawBytecodeHelper.LLOAD, 2, Kind.LOAD), - /** Load float from local variable */ + /** + * Load {@link TypeKind#FLOAT float} from local variable. + * + * @jvms 6.5.fload fload + * @see Kind#LOAD + */ FLOAD(RawBytecodeHelper.FLOAD, 2, Kind.LOAD), - /** Load double from local variable */ + /** + * Load {@link TypeKind#DOUBLE double} from local variable. + * + * @jvms 6.5.dload dload + * @see Kind#LOAD + */ DLOAD(RawBytecodeHelper.DLOAD, 2, Kind.LOAD), - /** Load reference from local variable */ + /** + * Load {@link TypeKind#REFERENCE reference} from local variable. + * + * @jvms 6.5.aload aload + * @see Kind#LOAD + */ ALOAD(RawBytecodeHelper.ALOAD, 2, Kind.LOAD), - /** Load int from local variable 0 */ + /** + * Load {@link TypeKind#INT int} from local variable slot {@code 0}. + * + * @jvms 6.5.iload_n iload_<n> + * @see Kind#LOAD + */ ILOAD_0(RawBytecodeHelper.ILOAD_0, 1, Kind.LOAD), - /** Load int from local variable 1 */ + /** + * Load {@link TypeKind#INT int} from local variable slot {@code 1}. + * + * @jvms 6.5.iload_n iload_<n> + * @see Kind#LOAD + */ ILOAD_1(RawBytecodeHelper.ILOAD_1, 1, Kind.LOAD), - /** Load int from local variable 2 */ + /** + * Load {@link TypeKind#INT int} from local variable slot {@code 2}. + * + * @jvms 6.5.iload_n iload_<n> + * @see Kind#LOAD + */ ILOAD_2(RawBytecodeHelper.ILOAD_2, 1, Kind.LOAD), - /** Load int from local variable3 */ + /** + * Load {@link TypeKind#INT int} from local variable slot {@code 3}. + * + * @jvms 6.5.iload_n iload_<n> + * @see Kind#LOAD + */ ILOAD_3(RawBytecodeHelper.ILOAD_3, 1, Kind.LOAD), - /** Load long from local variable 0 */ + /** + * Load {@link TypeKind#LONG long} from local variable slot {@code 0}. + * + * @jvms 6.5.lload_n lload_<n> + * @see Kind#LOAD + */ LLOAD_0(RawBytecodeHelper.LLOAD_0, 1, Kind.LOAD), - /** Load long from local variable 1 */ + /** + * Load {@link TypeKind#LONG long} from local variable slot {@code 1}. + * + * @jvms 6.5.lload_n lload_<n> + * @see Kind#LOAD + */ LLOAD_1(RawBytecodeHelper.LLOAD_1, 1, Kind.LOAD), - /** Load long from local variable 2 */ + /** + * Load {@link TypeKind#LONG long} from local variable slot {@code 2}. + * + * @jvms 6.5.lload_n lload_<n> + * @see Kind#LOAD + */ LLOAD_2(RawBytecodeHelper.LLOAD_2, 1, Kind.LOAD), - /** Load long from local variable 3 */ + /** + * Load {@link TypeKind#LONG long} from local variable slot {@code 3}. + * + * @jvms 6.5.lload_n lload_<n> + * @see Kind#LOAD + */ LLOAD_3(RawBytecodeHelper.LLOAD_3, 1, Kind.LOAD), - /** Load float from local variable 0 */ + /** + * Load {@link TypeKind#FLOAT float} from local variable slot {@code 0}. + * + * @jvms 6.5.fload_n fload_<n> + * @see Kind#LOAD + */ FLOAD_0(RawBytecodeHelper.FLOAD_0, 1, Kind.LOAD), - /** Load float from local variable 1 */ + /** + * Load {@link TypeKind#FLOAT float} from local variable slot {@code 1}. + * + * @jvms 6.5.fload_n fload_<n> + * @see Kind#LOAD + */ FLOAD_1(RawBytecodeHelper.FLOAD_1, 1, Kind.LOAD), - /** Load float from local variable 2 */ + /** + * Load {@link TypeKind#FLOAT float} from local variable slot {@code 2}. + * + * @jvms 6.5.fload_n fload_<n> + * @see Kind#LOAD + */ FLOAD_2(RawBytecodeHelper.FLOAD_2, 1, Kind.LOAD), - /** Load float from local variable 3 */ + /** + * Load {@link TypeKind#FLOAT float} from local variable slot {@code 3}. + * + * @jvms 6.5.fload_n fload_<n> + * @see Kind#LOAD + */ FLOAD_3(RawBytecodeHelper.FLOAD_3, 1, Kind.LOAD), - /** Load double from local variable 0 */ + /** + * Load {@link TypeKind#DOUBLE double} from local variable slot {@code 0}. + * + * @jvms 6.5.dload_n dload_<n> + * @see Kind#LOAD + */ DLOAD_0(RawBytecodeHelper.DLOAD_0, 1, Kind.LOAD), - /** Load double from local variable 1 */ + /** + * Load {@link TypeKind#DOUBLE double} from local variable slot {@code 1}. + * + * @jvms 6.5.dload_n dload_<n> + * @see Kind#LOAD + */ DLOAD_1(RawBytecodeHelper.DLOAD_1, 1, Kind.LOAD), - /** Load double from local variable 2 */ + /** + * Load {@link TypeKind#DOUBLE double} from local variable slot {@code 2}. + * + * @jvms 6.5.dload_n dload_<n> + * @see Kind#LOAD + */ DLOAD_2(RawBytecodeHelper.DLOAD_2, 1, Kind.LOAD), - /** Load double from local variable 3 */ + /** + * Load {@link TypeKind#DOUBLE double} from local variable slot {@code 3}. + * + * @jvms 6.5.dload_n dload_<n> + * @see Kind#LOAD + */ DLOAD_3(RawBytecodeHelper.DLOAD_3, 1, Kind.LOAD), - /** Load reference from local variable 0 */ + /** + * Load {@link TypeKind#REFERENCE reference} from local variable slot {@code 0}. + * + * @jvms 6.5.aload_n aload_<n> + * @see Kind#LOAD + */ ALOAD_0(RawBytecodeHelper.ALOAD_0, 1, Kind.LOAD), - /** Load reference from local variable 1 */ + /** + * Load {@link TypeKind#REFERENCE reference} from local variable slot {@code 1}. + * + * @jvms 6.5.aload_n aload_<n> + * @see Kind#LOAD + */ ALOAD_1(RawBytecodeHelper.ALOAD_1, 1, Kind.LOAD), - /** Load reference from local variable 2 */ + /** + * Load {@link TypeKind#REFERENCE reference} from local variable slot {@code 2}. + * + * @jvms 6.5.aload_n aload_<n> + * @see Kind#LOAD + */ ALOAD_2(RawBytecodeHelper.ALOAD_2, 1, Kind.LOAD), - /** Load reference from local variable 3 */ + /** + * Load {@link TypeKind#REFERENCE reference} from local variable slot {@code 3}. + * + * @jvms 6.5.aload_n aload_<n> + * @see Kind#LOAD + */ ALOAD_3(RawBytecodeHelper.ALOAD_3, 1, Kind.LOAD), - /** Load int from array */ + /** + * Load {@link TypeKind#INT int} from array. + * + * @jvms 6.5.iaload iaload + * @see Kind#ARRAY_LOAD + */ IALOAD(RawBytecodeHelper.IALOAD, 1, Kind.ARRAY_LOAD), - /** Load long from array */ + /** + * Load {@link TypeKind#LONG long} from array. + * + * @jvms 6.5.laload laload + * @see Kind#ARRAY_LOAD + */ LALOAD(RawBytecodeHelper.LALOAD, 1, Kind.ARRAY_LOAD), - /** Load float from array */ + /** + * Load {@link TypeKind#FLOAT float} from array. + * + * @jvms 6.5.faload faload + * @see Kind#ARRAY_LOAD + */ FALOAD(RawBytecodeHelper.FALOAD, 1, Kind.ARRAY_LOAD), - /** Load double from array */ + /** + * Load {@link TypeKind#DOUBLE double} from array. + * + * @jvms 6.5.daload daload + * @see Kind#ARRAY_LOAD + */ DALOAD(RawBytecodeHelper.DALOAD, 1, Kind.ARRAY_LOAD), - /** Load reference from array */ + /** + * Load {@link TypeKind#REFERENCE reference} from array. + * + * @jvms 6.5.aaload aaload + * @see Kind#ARRAY_LOAD + */ AALOAD(RawBytecodeHelper.AALOAD, 1, Kind.ARRAY_LOAD), - /** Load byte from array */ + /** + * Load {@link TypeKind#BYTE byte} or {@link TypeKind#BOOLEAN boolean} from array. + * + * @jvms 6.5.baload baload + * @see Kind#ARRAY_LOAD + */ BALOAD(RawBytecodeHelper.BALOAD, 1, Kind.ARRAY_LOAD), - /** Load char from array */ + /** + * Load {@link TypeKind#CHAR char} from array. + * + * @jvms 6.5.caload caload + * @see Kind#ARRAY_LOAD + */ CALOAD(RawBytecodeHelper.CALOAD, 1, Kind.ARRAY_LOAD), - /** Load short from array */ + /** + * Load {@link TypeKind#SHORT short} from array. + * + * @jvms 6.5.saload saload + * @see Kind#ARRAY_LOAD + */ SALOAD(RawBytecodeHelper.SALOAD, 1, Kind.ARRAY_LOAD), - /** Store int into local variable */ + /** + * Store {@link TypeKind#INT int} into local variable. + * + * @jvms 6.5.istore istore + * @see Kind#STORE + */ ISTORE(RawBytecodeHelper.ISTORE, 2, Kind.STORE), - /** Store long into local variable */ + /** + * Store {@link TypeKind#LONG long} into local variable. + * + * @jvms 6.5.lstore lstore + * @see Kind#STORE + */ LSTORE(RawBytecodeHelper.LSTORE, 2, Kind.STORE), - /** Store float into local variable */ + /** + * Store {@link TypeKind#FLOAT float} into local variable. + * + * @jvms 6.5.fstore fstore + * @see Kind#STORE + */ FSTORE(RawBytecodeHelper.FSTORE, 2, Kind.STORE), - /** Store double into local variable */ + /** + * Store {@link TypeKind#DOUBLE double} into local variable. + * + * @jvms 6.5.dstore dstore + * @see Kind#STORE + */ DSTORE(RawBytecodeHelper.DSTORE, 2, Kind.STORE), - /** Store reference into local variable */ + /** + * Store {@link TypeKind#REFERENCE reference} into local variable. + * Can also store the {@link TypeKind##returnAddress returnAddress} type. + * + * @jvms 6.5.astore astore + * @see Kind#STORE + */ ASTORE(RawBytecodeHelper.ASTORE, 2, Kind.STORE), - /** Store int into local variable 0 */ + /** + * Store {@link TypeKind#INT int} into local variable slot {@code 0}. + * + * @jvms 6.5.istore_n istore_<n> + * @see Kind#STORE + */ ISTORE_0(RawBytecodeHelper.ISTORE_0, 1, Kind.STORE), - /** Store int into local variable 1 */ + /** + * Store {@link TypeKind#INT int} into local variable slot {@code 1}. + * + * @jvms 6.5.istore_n istore_<n> + * @see Kind#STORE + */ ISTORE_1(RawBytecodeHelper.ISTORE_1, 1, Kind.STORE), - /** Store int into local variable 2 */ + /** + * Store {@link TypeKind#INT int} into local variable slot {@code 2}. + * + * @jvms 6.5.istore_n istore_<n> + * @see Kind#STORE + */ ISTORE_2(RawBytecodeHelper.ISTORE_2, 1, Kind.STORE), - /** Store int into local variable 3 */ + /** + * Store {@link TypeKind#INT int} into local variable slot {@code 3}. + * + * @jvms 6.5.istore_n istore_<n> + * @see Kind#STORE + */ ISTORE_3(RawBytecodeHelper.ISTORE_3, 1, Kind.STORE), - /** Store long into local variable 0 */ + /** + * Store {@link TypeKind#LONG long} into local variable slot {@code 0}. + * + * @jvms 6.5.lstore_n lstore_<n> + * @see Kind#STORE + */ LSTORE_0(RawBytecodeHelper.LSTORE_0, 1, Kind.STORE), - /** Store long into local variable 1 */ + /** + * Store {@link TypeKind#LONG long} into local variable slot {@code 1}. + * + * @jvms 6.5.lstore_n lstore_<n> + * @see Kind#STORE + */ LSTORE_1(RawBytecodeHelper.LSTORE_1, 1, Kind.STORE), - /** Store long into local variable 2 */ + /** + * Store {@link TypeKind#LONG long} into local variable slot {@code 2}. + * + * @jvms 6.5.lstore_n lstore_<n> + * @see Kind#STORE + */ LSTORE_2(RawBytecodeHelper.LSTORE_2, 1, Kind.STORE), - /** Store long into local variable 3 */ + /** + * Store {@link TypeKind#LONG long} into local variable slot {@code 3}. + * + * @jvms 6.5.lstore_n lstore_<n> + * @see Kind#STORE + */ LSTORE_3(RawBytecodeHelper.LSTORE_3, 1, Kind.STORE), - /** Store float into local variable 0 */ + /** + * Store {@link TypeKind#FLOAT float} into local variable slot {@code 0}. + * + * @jvms 6.5.fstore_n fstore_<n> + * @see Kind#STORE + */ FSTORE_0(RawBytecodeHelper.FSTORE_0, 1, Kind.STORE), - /** Store float into local variable 1 */ + /** + * Store {@link TypeKind#FLOAT float} into local variable slot {@code 1}. + * + * @jvms 6.5.fstore_n fstore_<n> + * @see Kind#STORE + */ FSTORE_1(RawBytecodeHelper.FSTORE_1, 1, Kind.STORE), - /** Store float into local variable 2 */ + /** + * Store {@link TypeKind#FLOAT float} into local variable slot {@code 2}. + * + * @jvms 6.5.fstore_n fstore_<n> + * @see Kind#STORE + */ FSTORE_2(RawBytecodeHelper.FSTORE_2, 1, Kind.STORE), - /** Store float into local variable 3 */ + /** + * Store {@link TypeKind#FLOAT float} into local variable slot {@code 3}. + * + * @jvms 6.5.fstore_n fstore_<n> + * @see Kind#STORE + */ FSTORE_3(RawBytecodeHelper.FSTORE_3, 1, Kind.STORE), - /** Store double into local variable 0 */ + /** + * Store {@link TypeKind#DOUBLE double} into local variable slot {@code 0}. + * + * @jvms 6.5.dstore_n dstore_<n> + * @see Kind#STORE + */ DSTORE_0(RawBytecodeHelper.DSTORE_0, 1, Kind.STORE), - /** Store double into local variable 1 */ + /** + * Store {@link TypeKind#DOUBLE double} into local variable slot {@code 1}. + * + * @jvms 6.5.dstore_n dstore_<n> + * @see Kind#STORE + */ DSTORE_1(RawBytecodeHelper.DSTORE_1, 1, Kind.STORE), - /** Store double into local variable 2 */ + /** + * Store {@link TypeKind#DOUBLE double} into local variable slot {@code 2}. + * + * @jvms 6.5.dstore_n dstore_<n> + * @see Kind#STORE + */ DSTORE_2(RawBytecodeHelper.DSTORE_2, 1, Kind.STORE), - /** Store double into local variable 3 */ + /** + * Store {@link TypeKind#DOUBLE double} into local variable slot {@code 3}. + * + * @jvms 6.5.dstore_n dstore_<n> + * @see Kind#STORE + */ DSTORE_3(RawBytecodeHelper.DSTORE_3, 1, Kind.STORE), - /** Store reference into local variable 0 */ + /** + * Store {@link TypeKind#REFERENCE reference} into local variable slot {@code 0}. + * Can also store the {@link TypeKind##returnAddress returnAddress} type. + * + * @jvms 6.5.astore_n astore_<n> + * @see Kind#STORE + */ ASTORE_0(RawBytecodeHelper.ASTORE_0, 1, Kind.STORE), - /** Store reference into local variable 1 */ + /** + * Store {@link TypeKind#REFERENCE reference} into local variable slot {@code 1}. + * Can also store the {@link TypeKind##returnAddress returnAddress} type. + * + * @jvms 6.5.astore_n astore_<n> + * @see Kind#STORE + */ ASTORE_1(RawBytecodeHelper.ASTORE_1, 1, Kind.STORE), - /** Store reference into local variable 2 */ + /** + * Store {@link TypeKind#REFERENCE reference} into local variable slot {@code 2}. + * Can also store the {@link TypeKind##returnAddress returnAddress} type. + * + * @jvms 6.5.astore_n astore_<n> + * @see Kind#STORE + */ ASTORE_2(RawBytecodeHelper.ASTORE_2, 1, Kind.STORE), - /** Store reference into local variable 3 */ + /** + * Store {@link TypeKind#REFERENCE reference} into local variable slot {@code 3}. + * Can also store the {@link TypeKind##returnAddress returnAddress} type. + * + * @jvms 6.5.astore_n astore_<n> + * @see Kind#STORE + */ ASTORE_3(RawBytecodeHelper.ASTORE_3, 1, Kind.STORE), - /** Store into int array */ + /** + * Store into {@link TypeKind#INT int} array. + * + * @jvms 6.5.iastore iastore + * @see Kind#ARRAY_STORE + */ IASTORE(RawBytecodeHelper.IASTORE, 1, Kind.ARRAY_STORE), - /** Store into long array */ + /** + * Store into {@link TypeKind#LONG long} array. + * + * @jvms 6.5.lastore lastore + * @see Kind#ARRAY_STORE + */ LASTORE(RawBytecodeHelper.LASTORE, 1, Kind.ARRAY_STORE), - /** Store into float array */ + /** + * Store into {@link TypeKind#FLOAT float} array. + * + * @jvms 6.5.fastore fastore + * @see Kind#ARRAY_STORE + */ FASTORE(RawBytecodeHelper.FASTORE, 1, Kind.ARRAY_STORE), - /** Store into double array */ + /** + * Store into {@link TypeKind#DOUBLE double} array. + * + * @jvms 6.5.dastore dastore + * @see Kind#ARRAY_STORE + */ DASTORE(RawBytecodeHelper.DASTORE, 1, Kind.ARRAY_STORE), - /** Store into reference array */ + /** + * Store into {@link TypeKind#REFERENCE reference} array. + * + * @jvms 6.5.aastore aastore + * @see Kind#ARRAY_STORE + */ AASTORE(RawBytecodeHelper.AASTORE, 1, Kind.ARRAY_STORE), - /** Store into byte array */ + /** + * Store into {@link TypeKind#BYTE byte} or {@link TypeKind#BOOLEAN boolean} array. + * + * @jvms 6.5.bastore bastore + * @see Kind#ARRAY_STORE + */ BASTORE(RawBytecodeHelper.BASTORE, 1, Kind.ARRAY_STORE), - /** Store into char array */ + /** + * Store into {@link TypeKind#CHAR char} array. + * + * @jvms 6.5.castore castore + * @see Kind#ARRAY_STORE + */ CASTORE(RawBytecodeHelper.CASTORE, 1, Kind.ARRAY_STORE), - /** Store into short array */ + /** + * Store into {@link TypeKind#SHORT short} array. + * + * @jvms 6.5.sastore sastore + * @see Kind#ARRAY_STORE + */ SASTORE(RawBytecodeHelper.SASTORE, 1, Kind.ARRAY_STORE), - /** Pop the top operand stack value */ + /** + * Pop the top operand stack value. + * + * @jvms 6.5.pop pop + * @see Kind#STACK + */ POP(RawBytecodeHelper.POP, 1, Kind.STACK), - /** Pop the top one or two operand stack values */ + /** + * Pop the top one or two operand stack values. + * + * @jvms 6.5.pop2 pop2 + * @see Kind#STACK + */ POP2(RawBytecodeHelper.POP2, 1, Kind.STACK), - /** Duplicate the top operand stack value */ + /** + * Duplicate the top operand stack value. + * + * @jvms 6.5.dup dup + * @see Kind#STACK + */ DUP(RawBytecodeHelper.DUP, 1, Kind.STACK), - /** Duplicate the top operand stack value and insert two values down */ + /** + * Duplicate the top operand stack value and insert two values down. + * + * @jvms 6.5.dup_x1 dup_x1 + * @see Kind#STACK + */ DUP_X1(RawBytecodeHelper.DUP_X1, 1, Kind.STACK), - /** Duplicate the top operand stack value and insert two or three values down */ + /** + * Duplicate the top operand stack value and insert two or three values down. + * + * @jvms 6.5.dup_x2 dup_x2 + * @see Kind#STACK + */ DUP_X2(RawBytecodeHelper.DUP_X2, 1, Kind.STACK), - /** Duplicate the top one or two operand stack values */ + /** + * Duplicate the top one or two operand stack values. + * + * @jvms 6.5.dup2 dup2 + * @see Kind#STACK + */ DUP2(RawBytecodeHelper.DUP2, 1, Kind.STACK), - /** Duplicate the top one or two operand stack values and insert two or three values down */ + /** + * Duplicate the top one or two operand stack values and insert two or three + * values down. + * + * @jvms 6.5.dup2_x1 dup2_x1 + * @see Kind#STACK + */ DUP2_X1(RawBytecodeHelper.DUP2_X1, 1, Kind.STACK), - /** Duplicate the top one or two operand stack values and insert two, three, or four values down */ + /** + * Duplicate the top one or two operand stack values and insert two, three, + * or four values down. + * + * @jvms 6.5.dup2_x2 dup2_x2 + * @see Kind#STACK + */ DUP2_X2(RawBytecodeHelper.DUP2_X2, 1, Kind.STACK), - /** Swap the top two operand stack values */ + /** + * Swap the top two operand stack values. + * + * @jvms 6.5.swap swap + * @see Kind#STACK + */ SWAP(RawBytecodeHelper.SWAP, 1, Kind.STACK), - /** Add int */ + /** + * Add {@link TypeKind#INT int}. + * + * @jvms 6.5.iadd iadd + * @see Kind#OPERATOR + */ IADD(RawBytecodeHelper.IADD, 1, Kind.OPERATOR), - /** Add long */ + /** + * Add {@link TypeKind#LONG long}. + * + * @jvms 6.5.ladd ladd + * @see Kind#OPERATOR + */ LADD(RawBytecodeHelper.LADD, 1, Kind.OPERATOR), - /** Add float */ + /** + * Add {@link TypeKind#FLOAT float}. + * + * @jvms 6.5.fadd fadd + * @see Kind#OPERATOR + */ FADD(RawBytecodeHelper.FADD, 1, Kind.OPERATOR), - /** Add double */ + /** + * Add {@link TypeKind#DOUBLE double}. + * + * @jvms 6.5.dadd dadd + * @see Kind#OPERATOR + */ DADD(RawBytecodeHelper.DADD, 1, Kind.OPERATOR), - /** Subtract int */ + /** + * Subtract {@link TypeKind#INT int}. + * + * @jvms 6.5.isub isub + * @see Kind#OPERATOR + */ ISUB(RawBytecodeHelper.ISUB, 1, Kind.OPERATOR), - /** Subtract long */ + /** + * Subtract {@link TypeKind#LONG long}. + * + * @jvms 6.5.lsub lsub + * @see Kind#OPERATOR + */ LSUB(RawBytecodeHelper.LSUB, 1, Kind.OPERATOR), - /** Subtract float */ + /** + * Subtract {@link TypeKind#FLOAT float}. + * + * @jvms 6.5.fsub fsub + * @see Kind#OPERATOR + */ FSUB(RawBytecodeHelper.FSUB, 1, Kind.OPERATOR), - /** Subtract double */ + /** + * Subtract {@link TypeKind#DOUBLE double}. + * + * @jvms 6.5.dsub dsub + * @see Kind#OPERATOR + */ DSUB(RawBytecodeHelper.DSUB, 1, Kind.OPERATOR), - /** Multiply int */ + /** + * Multiply {@link TypeKind#INT int}. + * + * @jvms 6.5.imul imul + * @see Kind#OPERATOR + */ IMUL(RawBytecodeHelper.IMUL, 1, Kind.OPERATOR), - /** Multiply long */ + /** + * Multiply {@link TypeKind#LONG long}. + * + * @jvms 6.5.lmul lmul + * @see Kind#OPERATOR + */ LMUL(RawBytecodeHelper.LMUL, 1, Kind.OPERATOR), - /** Multiply float */ + /** + * Multiply {@link TypeKind#FLOAT float}. + * + * @jvms 6.5.fmul fmul + * @see Kind#OPERATOR + */ FMUL(RawBytecodeHelper.FMUL, 1, Kind.OPERATOR), - /** Multiply double */ + /** + * Multiply {@link TypeKind#DOUBLE double}. + * + * @jvms 6.5.dmul dmul + * @see Kind#OPERATOR + */ DMUL(RawBytecodeHelper.DMUL, 1, Kind.OPERATOR), - /** Divide int */ + /** + * Divide {@link TypeKind#INT int}. + * + * @jvms 6.5.idiv idiv + * @see Kind#OPERATOR + */ IDIV(RawBytecodeHelper.IDIV, 1, Kind.OPERATOR), - /** Divide long */ + /** + * Divide {@link TypeKind#LONG long}. + * + * @jvms 6.5.ldiv ldiv + * @see Kind#OPERATOR + */ LDIV(RawBytecodeHelper.LDIV, 1, Kind.OPERATOR), - /** Divide float */ + /** + * Divide {@link TypeKind#FLOAT float}. + * + * @jvms 6.5.fdiv fdiv + * @see Kind#OPERATOR + */ FDIV(RawBytecodeHelper.FDIV, 1, Kind.OPERATOR), - /** Divide double */ + /** + * Divide {@link TypeKind#DOUBLE double}. + * + * @jvms 6.5.ddiv ddiv + * @see Kind#OPERATOR + */ DDIV(RawBytecodeHelper.DDIV, 1, Kind.OPERATOR), - /** Remainder int */ + /** + * Remainder {@link TypeKind#INT int}. + * + * @jvms 6.5.irem irem + * @see Kind#OPERATOR + */ IREM(RawBytecodeHelper.IREM, 1, Kind.OPERATOR), - /** Remainder long */ + /** + * Remainder {@link TypeKind#LONG long}. + * + * @jvms 6.5.lrem lrem + * @see Kind#OPERATOR + */ LREM(RawBytecodeHelper.LREM, 1, Kind.OPERATOR), - /** Remainder float */ + /** + * Remainder {@link TypeKind#FLOAT float}. + * + * @jvms 6.5.frem frem + * @see Kind#OPERATOR + */ FREM(RawBytecodeHelper.FREM, 1, Kind.OPERATOR), - /** Remainder double */ + /** + * Remainder {@link TypeKind#DOUBLE double}. + * + * @jvms 6.5.drem drem + * @see Kind#OPERATOR + */ DREM(RawBytecodeHelper.DREM, 1, Kind.OPERATOR), - /** Negate int */ + /** + * Negate {@link TypeKind#INT int}. + * + * @jvms 6.5.ineg ineg + * @see Kind#OPERATOR + */ INEG(RawBytecodeHelper.INEG, 1, Kind.OPERATOR), - /** Negate long */ + /** + * Negate {@link TypeKind#LONG long}. + * + * @jvms 6.5.lneg lneg + * @see Kind#OPERATOR + */ LNEG(RawBytecodeHelper.LNEG, 1, Kind.OPERATOR), - /** Negate float */ + /** + * Negate {@link TypeKind#FLOAT float}. + * + * @jvms 6.5.fneg fneg + * @see Kind#OPERATOR + */ FNEG(RawBytecodeHelper.FNEG, 1, Kind.OPERATOR), - /** Negate double */ + /** + * Negate {@link TypeKind#DOUBLE double}. + * + * @jvms 6.5.dneg dneg + * @see Kind#OPERATOR + */ DNEG(RawBytecodeHelper.DNEG, 1, Kind.OPERATOR), - /** Shift left int */ + /** + * Shift left {@link TypeKind#INT int}. + * + * @jvms 6.5.ishl ishl + * @see Kind#OPERATOR + */ ISHL(RawBytecodeHelper.ISHL, 1, Kind.OPERATOR), - /** Shift left long */ + /** + * Shift left {@link TypeKind#LONG long}. + * + * @jvms 6.5.lshl lshl + * @see Kind#OPERATOR + */ LSHL(RawBytecodeHelper.LSHL, 1, Kind.OPERATOR), - /** Shift right int */ + /** + * Arithmetic shift right {@link TypeKind#INT int}. + * + * @jvms 6.5.ishr ishr + * @see Kind#OPERATOR + */ ISHR(RawBytecodeHelper.ISHR, 1, Kind.OPERATOR), - /** Shift right long */ + /** + * Arithmetic shift right {@link TypeKind#LONG long}. + * + * @jvms 6.5.lshr lshr + * @see Kind#OPERATOR + */ LSHR(RawBytecodeHelper.LSHR, 1, Kind.OPERATOR), - /** Logical shift right int */ + /** + * Logical shift right {@link TypeKind#INT int}. + * + * @jvms 6.5.iushr iushr + * @see Kind#OPERATOR + */ IUSHR(RawBytecodeHelper.IUSHR, 1, Kind.OPERATOR), - /** Logical shift right long */ + /** + * Logical shift right {@link TypeKind#LONG long}. + * + * @jvms 6.5.lushr lushr + * @see Kind#OPERATOR + */ LUSHR(RawBytecodeHelper.LUSHR, 1, Kind.OPERATOR), - /** Boolean AND int */ + /** + * Bitwise AND {@link TypeKind#INT int}. + * + * @apiNote + * This may be used to implement {@link TypeKind#BOOLEAN boolean} AND. + * + * @jvms 6.5.iand iand + * @see Kind#OPERATOR + */ IAND(RawBytecodeHelper.IAND, 1, Kind.OPERATOR), - /** Boolean AND long */ + /** + * Bitwise AND {@link TypeKind#LONG long}. + * + * @jvms 6.5.land land + * @see Kind#OPERATOR + */ LAND(RawBytecodeHelper.LAND, 1, Kind.OPERATOR), - /** Boolean OR int */ + /** + * Bitwise OR {@link TypeKind#INT int}. + * + * @apiNote + * This may be used to implement {@link TypeKind#BOOLEAN boolean} OR. + * + * @jvms 6.5.ior ior + * @see Kind#OPERATOR + */ IOR(RawBytecodeHelper.IOR, 1, Kind.OPERATOR), - /** Boolean OR long */ + /** + * Bitwise OR {@link TypeKind#LONG long}. + * + * @jvms 6.5.lor lor + * @see Kind#OPERATOR + */ LOR(RawBytecodeHelper.LOR, 1, Kind.OPERATOR), - /** Boolean XOR int */ + /** + * Bitwise XOR {@link TypeKind#INT int}. + * + * @apiNote + * This may be used to implement {@link TypeKind#BOOLEAN boolean} XOR. + * + * @jvms 6.5.ixor ixor + * @see Kind#OPERATOR + */ IXOR(RawBytecodeHelper.IXOR, 1, Kind.OPERATOR), - /** Boolean XOR long */ + /** + * Bitwise XOR {@link TypeKind#LONG long}. + * + * @jvms 6.5.lxor lxor + * @see Kind#OPERATOR + */ LXOR(RawBytecodeHelper.LXOR, 1, Kind.OPERATOR), - /** Increment local variable by constant */ + /** + * Increment local variable by constant. + * + * @jvms 6.5.iinc iinc + * @see Kind#INCREMENT + */ IINC(RawBytecodeHelper.IINC, 3, Kind.INCREMENT), - /** Convert int to long */ + /** + * Convert {@link TypeKind#INT int} to {@link TypeKind#LONG long}. + * + * @jls 5.1.2 Widening Primitive Conversion + * @jvms 6.5.i2l i2l + * @see Kind#CONVERT + */ I2L(RawBytecodeHelper.I2L, 1, Kind.CONVERT), - /** Convert int to float */ + /** + * Convert {@link TypeKind#INT int} to {@link TypeKind#FLOAT float}. + * + * @jls 5.1.2 Widening Primitive Conversion + * @jvms 6.5.i2f i2f + * @see Kind#CONVERT + */ I2F(RawBytecodeHelper.I2F, 1, Kind.CONVERT), - /** Convert int to double */ + /** + * Convert {@link TypeKind#INT int} to {@link TypeKind#DOUBLE double}. + * + * @jls 5.1.2 Widening Primitive Conversion + * @jvms 6.5.i2d i2d + * @see Kind#CONVERT + */ I2D(RawBytecodeHelper.I2D, 1, Kind.CONVERT), - /** Convert long to int */ + /** + * Convert {@link TypeKind#LONG long} to {@link TypeKind#INT int}. + * + * @jls 5.1.3 Narrowing Primitive Conversion + * @jvms 6.5.l2i l2i + * @see Kind#CONVERT + */ L2I(RawBytecodeHelper.L2I, 1, Kind.CONVERT), - /** Convert long to float */ + /** Convert {@link TypeKind#LONG long} to {@link TypeKind#FLOAT float}. + * + * @jls 5.1.2 Widening Primitive Conversion + * @jvms 6.5.l2f l2f + * @see Kind#CONVERT + */ L2F(RawBytecodeHelper.L2F, 1, Kind.CONVERT), - /** Convert long to double */ + /** Convert {@link TypeKind#LONG long} to {@link TypeKind#DOUBLE double}. + * + * @jls 5.1.2 Widening Primitive Conversion + * @jvms 6.5.l2d l2d + * @see Kind#CONVERT + */ L2D(RawBytecodeHelper.L2D, 1, Kind.CONVERT), - /** Convert float to int */ + /** + * Convert {@link TypeKind#FLOAT float} to {@link TypeKind#INT int}. + * + * @jls 5.1.3 Narrowing Primitive Conversion + * @jvms 6.5.f2i f2i + * @see Kind#CONVERT + */ F2I(RawBytecodeHelper.F2I, 1, Kind.CONVERT), - /** Convert float to long */ + /** + * Convert {@link TypeKind#FLOAT float} to {@link TypeKind#LONG long}. + * + * @jls 5.1.3 Narrowing Primitive Conversion + * @jvms 6.5.f2l f2l + * @see Kind#CONVERT + */ F2L(RawBytecodeHelper.F2L, 1, Kind.CONVERT), - /** Convert float to double */ + /** + * Convert {@link TypeKind#FLOAT float} to {@link TypeKind#DOUBLE double}. + * + * @jls 5.1.2 Widening Primitive Conversion + * @jvms 6.5.f2d f2d + * @see Kind#CONVERT + */ F2D(RawBytecodeHelper.F2D, 1, Kind.CONVERT), - /** Convert double to int */ + /** + * Convert {@link TypeKind#DOUBLE double} to {@link TypeKind#INT int}. + * + * @jls 5.1.3 Narrowing Primitive Conversion + * @jvms 6.5.d2i d2i + * @see Kind#CONVERT + */ D2I(RawBytecodeHelper.D2I, 1, Kind.CONVERT), - /** Convert double to long */ + /** + * Convert {@link TypeKind#DOUBLE double} to {@link TypeKind#LONG long}. + * + * @jvms 6.5.d2l d2l + * @see Kind#CONVERT + */ D2L(RawBytecodeHelper.D2L, 1, Kind.CONVERT), - /** Convert double to float */ + /** + * Convert {@link TypeKind#DOUBLE double} to {@link TypeKind#FLOAT float}. + * + * @jls 5.1.3 Narrowing Primitive Conversion + * @jvms 6.5.d2f d2f + * @see Kind#CONVERT + */ D2F(RawBytecodeHelper.D2F, 1, Kind.CONVERT), - /** Convert int to byte */ + /** + * Convert {@link TypeKind#INT int} to {@link TypeKind#BYTE byte}. + * This is as if storing the {@linkplain TypeKind##computational-type + * computational} {@code int} into a {@code byte} and loading it back. + * + * @jls 5.1.3 Narrowing Primitive Conversion + * @jvms 6.5.i2b i2b + * @see Kind#CONVERT + */ I2B(RawBytecodeHelper.I2B, 1, Kind.CONVERT), - /** Convert int to char */ + /** + * Convert {@link TypeKind#INT int} to {@link TypeKind#CHAR char}. + * This is as if storing the {@linkplain TypeKind##computational-type + * computational} {@code int} into a {@code char} and loading it back. + * + * @jls 5.1.3 Narrowing Primitive Conversion + * @jvms 6.5.i2c i2c + * @see Kind#CONVERT + */ I2C(RawBytecodeHelper.I2C, 1, Kind.CONVERT), - /** Convert int to short */ + /** + * Convert {@link TypeKind#INT int} to {@link TypeKind#SHORT short}. + * This is as if storing the {@linkplain TypeKind##computational-type + * computational} {@code int} into a {@code short} and loading it back. + * + * @jls 5.1.3 Narrowing Primitive Conversion + * @jvms 6.5.i2s i2s + * @see Kind#CONVERT + */ I2S(RawBytecodeHelper.I2S, 1, Kind.CONVERT), - /** Compare long */ + /** + * Compare {@link TypeKind#LONG long}. + * + * @see Long#compare(long, long) + * @jvms 6.5.lcmp lcmp + * @see Kind#OPERATOR + */ LCMP(RawBytecodeHelper.LCMP, 1, Kind.OPERATOR), - /** Compare float */ + /** + * Compare {@link TypeKind#FLOAT float}. + * Produces {@code -1} if any operand is {@link Float#isNaN(float) NaN}. + * + * @see Double##equivalenceRelation Floating-point Equality, Equivalence, and Comparison + * @jvms 6.5.fcmp_op fcmp<op> + * @see Kind#OPERATOR + */ FCMPL(RawBytecodeHelper.FCMPL, 1, Kind.OPERATOR), - /** Compare float */ + /** + * Compare {@link TypeKind#FLOAT float}. + * Produces {@code 1} if any operand is {@link Float#isNaN(float) NaN}. + * + * @see Double##equivalenceRelation Floating-point Equality, Equivalence, and Comparison + * @jvms 6.5.fcmp_op fcmp<op> + * @see Kind#OPERATOR + */ FCMPG(RawBytecodeHelper.FCMPG, 1, Kind.OPERATOR), - /** Compare double */ + /** + * Compare {@link TypeKind#DOUBLE double}. + * Produces {@code -1} if any operand is {@link Double#isNaN(double) NaN}. + * + * @see Double##equivalenceRelation Floating-point Equality, Equivalence, and Comparison + * @jvms 6.5.dcmp_op dcmp<op> + * @see Kind#OPERATOR + */ DCMPL(RawBytecodeHelper.DCMPL, 1, Kind.OPERATOR), - /** Compare double */ + /** + * Compare {@link TypeKind#DOUBLE double}. + * Produces {@code 1} if any operand is {@link Double#isNaN(double) NaN}. + * + * @see Double##equivalenceRelation Floating-point Equality, Equivalence, and Comparison + * @jvms 6.5.dcmp_op dcmp<op> + * @see Kind#OPERATOR + */ DCMPG(RawBytecodeHelper.DCMPG, 1, Kind.OPERATOR), - /** Branch if int comparison with zero succeeds */ + /** + * Branch if {@link TypeKind#INT int} comparison {@code == 0} succeeds. + * + * @jvms 6.5.if_cond if_<cond> + * @see Kind#BRANCH + */ IFEQ(RawBytecodeHelper.IFEQ, 3, Kind.BRANCH), - /** Branch if int comparison with zero succeeds */ + /** + * Branch if {@link TypeKind#INT int} comparison {@code != 0} succeeds. + * + * @jvms 6.5.if_cond if_<cond> + * @see Kind#BRANCH + */ IFNE(RawBytecodeHelper.IFNE, 3, Kind.BRANCH), - /** Branch if int comparison with zero succeeds */ + /** + * Branch if {@link TypeKind#INT int} comparison {@code < 0} succeeds. + * + * @jvms 6.5.if_cond if_<cond> + * @see Kind#BRANCH + */ IFLT(RawBytecodeHelper.IFLT, 3, Kind.BRANCH), - /** Branch if int comparison with zero succeeds */ + /** + * Branch if {@link TypeKind#INT int} comparison {@code >= 0} succeeds. + * + * @jvms 6.5.if_cond if_<cond> + * @see Kind#BRANCH + */ IFGE(RawBytecodeHelper.IFGE, 3, Kind.BRANCH), - /** Branch if int comparison with zero succeeds */ + /** + * Branch if {@link TypeKind#INT int} comparison {@code > 0} succeeds. + * + * @jvms 6.5.if_cond if_<cond> + * @see Kind#BRANCH + */ IFGT(RawBytecodeHelper.IFGT, 3, Kind.BRANCH), - /** Branch if int comparison with zero succeeds */ + /** + * Branch if {@link TypeKind#INT int} comparison {@code <= 0} succeeds. + * + * @jvms 6.5.if_cond if_<cond> + * @see Kind#BRANCH + */ IFLE(RawBytecodeHelper.IFLE, 3, Kind.BRANCH), - /** Branch if int comparison succeeds */ + /** + * Branch if {@link TypeKind#INT int} comparison {@code operand1 == operand2} succeeds. + * + * @jvms 6.5.if_icmp_cond if_icmp<cond> + * @see Kind#BRANCH + */ IF_ICMPEQ(RawBytecodeHelper.IF_ICMPEQ, 3, Kind.BRANCH), - /** Branch if int comparison succeeds */ + /** + * Branch if {@link TypeKind#INT int} comparison {@code operand1 != operand2} succeeds. + * + * @jvms 6.5.if_icmp_cond if_icmp<cond> + * @see Kind#BRANCH + */ IF_ICMPNE(RawBytecodeHelper.IF_ICMPNE, 3, Kind.BRANCH), - /** Branch if int comparison succeeds */ + /** + * Branch if {@link TypeKind#INT int} comparison {@code operand1 < operand2} succeeds. + * + * @jvms 6.5.if_icmp_cond if_icmp<cond> + * @see Kind#BRANCH + */ IF_ICMPLT(RawBytecodeHelper.IF_ICMPLT, 3, Kind.BRANCH), - /** Branch if int comparison succeeds */ + /** + * Branch if {@link TypeKind#INT int} comparison {@code operand1 >= operand2} succeeds. + * + * @jvms 6.5.if_icmp_cond if_icmp<cond> + * @see Kind#BRANCH + */ IF_ICMPGE(RawBytecodeHelper.IF_ICMPGE, 3, Kind.BRANCH), - /** Branch if int comparison succeeds */ + /** + * Branch if {@link TypeKind#INT int} comparison {@code operand1 > operand2} succeeds. + * + * @jvms 6.5.if_icmp_cond if_icmp<cond> + * @see Kind#BRANCH + */ IF_ICMPGT(RawBytecodeHelper.IF_ICMPGT, 3, Kind.BRANCH), - /** Branch if int comparison succeeds */ + /** + * Branch if {@link TypeKind#INT int} comparison {@code operand1 <= operand2} succeeds. + * + * @jvms 6.5.if_icmp_cond if_icmp<cond> + * @see Kind#BRANCH + */ IF_ICMPLE(RawBytecodeHelper.IF_ICMPLE, 3, Kind.BRANCH), - /** Branch if reference comparison succeeds */ + /** + * Branch if {@link TypeKind#REFERENCE reference} comparison + * {@code operand1 == operand2} succeeds. + * + * @jvms 6.5.if_acmp_cond if_acmp<cond> + * @see Kind#BRANCH + */ IF_ACMPEQ(RawBytecodeHelper.IF_ACMPEQ, 3, Kind.BRANCH), - /** Branch if reference comparison succeeds */ + /** + * Branch if {@link TypeKind#REFERENCE reference} comparison + * {@code operand1 != operand2} succeeds. + * + * @jvms 6.5.if_acmp_cond if_acmp<cond> + * @see Kind#BRANCH + */ IF_ACMPNE(RawBytecodeHelper.IF_ACMPNE, 3, Kind.BRANCH), - /** Branch always */ + /** + * Branch always. + * + * @jvms 6.5.goto goto + * @see Kind#BRANCH + */ GOTO(RawBytecodeHelper.GOTO, 3, Kind.BRANCH), /** - * Jump subroutine is discontinued opcode - * @see java.lang.classfile.instruction.DiscontinuedInstruction + * (Discontinued) Jump subroutine; last used in major version {@value + * ClassFile#JAVA_6_VERSION}. + * + * @jvms 4.9.1 Static Constraints + * @jvms 6.5.jsr jsr + * @see Kind#DISCONTINUED_JSR */ JSR(RawBytecodeHelper.JSR, 3, Kind.DISCONTINUED_JSR), /** - * Return from subroutine is discontinued opcode - * @see java.lang.classfile.instruction.DiscontinuedInstruction + * (Discontinued) Return from subroutine; last used in major version + * {@value ClassFile#JAVA_6_VERSION}. + * + * @jvms 4.9.1 Static Constraints + * @jvms 6.5.ret ret + * @see Kind#DISCONTINUED_RET */ RET(RawBytecodeHelper.RET, 2, Kind.DISCONTINUED_RET), - /** Access jump table by index and jump */ + /** + * Access jump table by index and jump. + * + * @jvms 6.5.tableswitch tableswitch + * @see Kind#TABLE_SWITCH + */ TABLESWITCH(RawBytecodeHelper.TABLESWITCH, -1, Kind.TABLE_SWITCH), - /** Access jump table by key match and jump */ + /** + * Access jump table by key match and jump. + * + * @jvms 6.5.lookupswitch lookupswitch + * @see Kind#LOOKUP_SWITCH + */ LOOKUPSWITCH(RawBytecodeHelper.LOOKUPSWITCH, -1, Kind.LOOKUP_SWITCH), - /** Return int from method */ + /** + * Return {@link TypeKind#INT int} from method. + * + * @jvms 6.5.ireturn ireturn + * @see Kind#RETURN + */ IRETURN(RawBytecodeHelper.IRETURN, 1, Kind.RETURN), - /** Return long from method */ + /** + * Return {@link TypeKind#LONG long} from method. + * + * @jvms 6.5.lreturn lreturn + * @see Kind#RETURN + */ LRETURN(RawBytecodeHelper.LRETURN, 1, Kind.RETURN), - /** Return float from method */ + /** + * Return {@link TypeKind#FLOAT float} from method. + * + * @jvms 6.5.freturn freturn + * @see Kind#RETURN + */ FRETURN(RawBytecodeHelper.FRETURN, 1, Kind.RETURN), - /** Return double from method */ + /** + * Return {@link TypeKind#DOUBLE double} from method. + * + * @jvms 6.5.dreturn dreturn + * @see Kind#RETURN + */ DRETURN(RawBytecodeHelper.DRETURN, 1, Kind.RETURN), - /** Return reference from method */ + /** + * Return {@link TypeKind#REFERENCE reference} from method. + * + * @jvms 6.5.areturn areturn + * @see Kind#RETURN + */ ARETURN(RawBytecodeHelper.ARETURN, 1, Kind.RETURN), - /** Return void from method */ + /** + * Return {@link TypeKind#VOID void} from method. + * + * @jvms 6.5.return return + * @see Kind#RETURN + */ RETURN(RawBytecodeHelper.RETURN, 1, Kind.RETURN), - /** Get static field from class */ + /** + * Get {@code static} field from class. + * + * @jvms 6.5.getstatic getstatic + * @see Kind#FIELD_ACCESS + */ GETSTATIC(RawBytecodeHelper.GETSTATIC, 3, Kind.FIELD_ACCESS), - /** Set static field in class */ + /** + * Set {@code static} field in class. + * + * @jvms 6.5.putstatic putstatic + * @see Kind#FIELD_ACCESS + */ PUTSTATIC(RawBytecodeHelper.PUTSTATIC, 3, Kind.FIELD_ACCESS), - /** Fetch field from object */ + /** + * Fetch field from object. + * + * @jvms 6.5.getfield getfield + * @see Kind#FIELD_ACCESS + */ GETFIELD(RawBytecodeHelper.GETFIELD, 3, Kind.FIELD_ACCESS), - /** Set field in object */ + /** + * Set field in object. + * + * @jvms 6.5.putfield putfield + * @see Kind#FIELD_ACCESS + */ PUTFIELD(RawBytecodeHelper.PUTFIELD, 3, Kind.FIELD_ACCESS), - /** Invoke instance method; dispatch based on class */ + /** + * Invoke instance method; dispatch based on class. + * + * @jvms 6.5.invokevirtual invokevirtual + * @see Kind#INVOKE + */ INVOKEVIRTUAL(RawBytecodeHelper.INVOKEVIRTUAL, 3, Kind.INVOKE), /** * Invoke instance method; direct invocation of instance initialization - * methods and methods of the current class and its supertypes + * methods and methods of the current class and its supertypes. + * + * @jvms 6.5.invokevirtual invokevirtual + * @see Kind#INVOKE */ INVOKESPECIAL(RawBytecodeHelper.INVOKESPECIAL, 3, Kind.INVOKE), - /** Invoke a class (static) method */ + /** + * Invoke a class ({@code static}) method. + * + * @jvms 6.5.invokestatic invokestatic + * @see Kind#INVOKE + */ INVOKESTATIC(RawBytecodeHelper.INVOKESTATIC, 3, Kind.INVOKE), - /** Invoke interface method */ + /** + * Invoke interface method. + * + * @jvms 6.5.invokeinterface invokeinterface + * @see Kind#INVOKE + */ INVOKEINTERFACE(RawBytecodeHelper.INVOKEINTERFACE, 5, Kind.INVOKE), - /** Invoke a dynamically-computed call site */ + /** + * Invoke a dynamically-computed call site. + * + * @jvms 6.5.invokedynamic invokedynamic + * @see Kind#INVOKE_DYNAMIC + */ INVOKEDYNAMIC(RawBytecodeHelper.INVOKEDYNAMIC, 5, Kind.INVOKE_DYNAMIC), - /** Create new object */ + /** + * Create new object. + * + * @jvms 6.5.new new + * @see Kind#NEW_OBJECT + */ NEW(RawBytecodeHelper.NEW, 3, Kind.NEW_OBJECT), - /** Create new array */ + /** + * Create new array. + * + * @jvms 6.5.newarray newarray + * @see Kind#NEW_PRIMITIVE_ARRAY + */ NEWARRAY(RawBytecodeHelper.NEWARRAY, 2, Kind.NEW_PRIMITIVE_ARRAY), - /** Create new array of reference */ + /** + * Create new array of {@link TypeKind#REFERENCE reference}. + * + * @jvms 6.5.anewarray anewarray + * @see Kind#NEW_REF_ARRAY + */ ANEWARRAY(RawBytecodeHelper.ANEWARRAY, 3, Kind.NEW_REF_ARRAY), - /** Get length of array */ + /** + * Get length of array. + * + * @jvms 6.5.arraylength arraylength + * @see Kind#OPERATOR + */ ARRAYLENGTH(RawBytecodeHelper.ARRAYLENGTH, 1, Kind.OPERATOR), - /** Throw exception or error */ + /** + * Throw exception or error. + * + * @jvms 6.5.athrow athrow + * @see Kind#THROW_EXCEPTION + */ ATHROW(RawBytecodeHelper.ATHROW, 1, Kind.THROW_EXCEPTION), - /** Check whether object is of given type */ + /** + * Check whether object is of given type. + * + * @see Class#cast(Object) + * @jvms 6.5.checkcast checkcast + * @see Kind#TYPE_CHECK + */ CHECKCAST(RawBytecodeHelper.CHECKCAST, 3, Kind.TYPE_CHECK), - /** Determine if object is of given type */ + /** + * Determine if object is of given type. + * + * @see Class#isInstance(Object) + * @jvms 6.5.instanceof instanceof + * @see Kind#TYPE_CHECK + */ INSTANCEOF(RawBytecodeHelper.INSTANCEOF, 3, Kind.TYPE_CHECK), - /** Enter monitor for object */ + /** + * Enter monitor for object. + * + * @jvms 6.5.monitorenter monitorenter + * @see Kind#MONITOR + */ MONITORENTER(RawBytecodeHelper.MONITORENTER, 1, Kind.MONITOR), - /** Exit monitor for object */ + /** + * Exit monitor for object. + * + * @jvms 6.5.monitorexit monitorexit + * @see Kind#MONITOR + */ MONITOREXIT(RawBytecodeHelper.MONITOREXIT, 1, Kind.MONITOR), - /** Create new multidimensional array */ + /** + * Create new multidimensional array. + * + * @jvms 6.5.multianewarray multianewarray + * @see Kind#NEW_MULTI_ARRAY + */ MULTIANEWARRAY(RawBytecodeHelper.MULTIANEWARRAY, 4, Kind.NEW_MULTI_ARRAY), - /** Branch if reference is null */ + /** + * Branch if {@link TypeKind#REFERENCE reference} is {@code null}. + * + * @jvms 6.5.ifnull ifnull + * @see Kind#BRANCH + */ IFNULL(RawBytecodeHelper.IFNULL, 3, Kind.BRANCH), - /** Branch if reference not null */ + /** + * Branch if {@link TypeKind#REFERENCE reference} is not {@code null}. + * + * @jvms 6.5.ifnonnull ifnonnull + * @see Kind#BRANCH + */ IFNONNULL(RawBytecodeHelper.IFNONNULL, 3, Kind.BRANCH), - /** Branch always (wide index) */ + /** + * Branch always (wide index). + * + * @jvms 6.5.goto_w goto_w + * @see Kind#BRANCH + */ GOTO_W(RawBytecodeHelper.GOTO_W, 5, Kind.BRANCH), /** - * Jump subroutine (wide index) is discontinued opcode - * @see java.lang.classfile.instruction.DiscontinuedInstruction + * (Discontinued) Jump subroutine (wide index); last used in major + * version {@value ClassFile#JAVA_6_VERSION}. + * + * @jvms 4.9.1 Static Constraints + * @jvms 6.5.jsr_w jsr_w + * @see Kind#DISCONTINUED_JSR */ JSR_W(RawBytecodeHelper.JSR_W, 5, Kind.DISCONTINUED_JSR), - /** Load int from local variable (wide index) */ + /** + * Load {@link TypeKind#INT int} from local variable (wide index). + * This is a {@linkplain #isWide() wide}-modified pseudo-opcode. + * + * @jvms 6.5.wide wide + * @jvms 6.5.iload iload + * @see Kind#LOAD + */ ILOAD_W((RawBytecodeHelper.WIDE << 8) | RawBytecodeHelper.ILOAD, 4, Kind.LOAD), - /** Load long from local variable (wide index) */ + /** + * Load {@link TypeKind#LONG long} from local variable (wide index). + * This is a {@linkplain #isWide() wide}-modified pseudo-opcode. + * + * @jvms 6.5.wide wide + * @jvms 6.5.lload lload + * @see Kind#LOAD + */ LLOAD_W((RawBytecodeHelper.WIDE << 8) | RawBytecodeHelper.LLOAD, 4, Kind.LOAD), - /** Load float from local variable (wide index) */ + /** + * Load {@link TypeKind#FLOAT float} from local variable (wide index). + * This is a {@linkplain #isWide() wide}-modified pseudo-opcode. + * + * @jvms 6.5.wide wide + * @jvms 6.5.fload fload + * @see Kind#LOAD + */ FLOAD_W((RawBytecodeHelper.WIDE << 8) | RawBytecodeHelper.FLOAD, 4, Kind.LOAD), - /** Load double from local variable (wide index) */ + /** + * Load {@link TypeKind#DOUBLE double} from local variable (wide index). + * This is a {@linkplain #isWide() wide}-modified pseudo-opcode. + * + * @jvms 6.5.wide wide + * @jvms 6.5.dload dload + * @see Kind#LOAD + */ DLOAD_W((RawBytecodeHelper.WIDE << 8) | RawBytecodeHelper.DLOAD, 4, Kind.LOAD), - /** Load reference from local variable (wide index) */ + /** + * Load {@link TypeKind#REFERENCE reference} from local variable (wide index). + * This is a {@linkplain #isWide() wide}-modified pseudo-opcode. + * + * @jvms 6.5.wide wide + * @jvms 6.5.aload aload + * @see Kind#LOAD + */ ALOAD_W((RawBytecodeHelper.WIDE << 8) | RawBytecodeHelper.ALOAD, 4, Kind.LOAD), - /** Store int into local variable (wide index) */ + /** + * Store {@link TypeKind#INT int} into local variable (wide index). + * This is a {@linkplain #isWide() wide}-modified pseudo-opcode. + * + * @jvms 6.5.wide wide + * @jvms 6.5.istore istore + * @see Kind#STORE + */ ISTORE_W((RawBytecodeHelper.WIDE << 8) | RawBytecodeHelper.ISTORE, 4, Kind.STORE), - /** Store long into local variable (wide index) */ + /** + * Store {@link TypeKind#LONG long} into local variable (wide index). + * This is a {@linkplain #isWide() wide}-modified pseudo-opcode. + * + * @jvms 6.5.wide wide + * @jvms 6.5.lstore lstore + * @see Kind#STORE + */ LSTORE_W((RawBytecodeHelper.WIDE << 8) | RawBytecodeHelper.LSTORE, 4, Kind.STORE), - /** Store float into local variable (wide index) */ + /** + * Store {@link TypeKind#FLOAT float} into local variable (wide index). + * This is a {@linkplain #isWide() wide}-modified pseudo-opcode. + * + * @jvms 6.5.wide wide + * @jvms 6.5.fstore fstore + * @see Kind#STORE + */ FSTORE_W((RawBytecodeHelper.WIDE << 8) | RawBytecodeHelper.FSTORE, 4, Kind.STORE), - /** Store double into local variable (wide index) */ + /** + * Store {@link TypeKind#DOUBLE double} into local variable (wide index). + * This is a {@linkplain #isWide() wide}-modified pseudo-opcode. + * + * @jvms 6.5.wide wide + * @jvms 6.5.dstore dstore + * @see Kind#STORE + */ DSTORE_W((RawBytecodeHelper.WIDE << 8) | RawBytecodeHelper.DSTORE, 4, Kind.STORE), - /** Store reference into local variable (wide index) */ + /** + * Store {@link TypeKind#REFERENCE reference} into local variable (wide index). + * This is a {@linkplain #isWide() wide}-modified pseudo-opcode. + * Can also store the {@link TypeKind##returnAddress returnAddress} type. + * + * @jvms 6.5.wide wide + * @jvms 6.5.astore astore + * @see Kind#STORE + */ ASTORE_W((RawBytecodeHelper.WIDE << 8) | RawBytecodeHelper.ASTORE, 4, Kind.STORE), /** - * Return from subroutine (wide index) is discontinued opcode - * @see java.lang.classfile.instruction.DiscontinuedInstruction + * (Discontinued) Return from subroutine (wide index); last used in major + * version {@value ClassFile#JAVA_6_VERSION}. + * This is a {@linkplain #isWide() wide}-modified pseudo-opcode. + * + * @jvms 4.9.1 Static Constraints + * @jvms 6.5.wide wide + * @jvms 6.5.ret ret + * @see Kind#DISCONTINUED_RET */ RET_W((RawBytecodeHelper.WIDE << 8) | RawBytecodeHelper.RET, 4, Kind.DISCONTINUED_RET), - /** Increment local variable by constant (wide index) */ + /** + * Increment local variable by constant (wide index). + * This is a {@linkplain #isWide() wide}-modified pseudo-opcode. + * + * @jvms 6.5.wide wide + * @jvms 6.5.iinc iinc + * @see Kind#INCREMENT + */ IINC_W((RawBytecodeHelper.WIDE << 8) | RawBytecodeHelper.IINC, 6, Kind.INCREMENT); /** - * Kinds of opcodes. + * Kinds of opcodes. Each kind of opcode has its own modeling interface + * for its instructions. * * @since 24 */ - public static enum Kind { + public enum Kind { /** - * Load from local variable + * Load from local variable. * + * @see LoadInstruction * @see Opcode#ILOAD * @see Opcode#LLOAD * @see Opcode#FLOAD @@ -736,8 +1901,9 @@ public static enum Kind { LOAD, /** - * Store into local variable + * Store into local variable. * + * @see StoreInstruction * @see Opcode#ISTORE * @see Opcode#LSTORE * @see Opcode#FSTORE @@ -772,16 +1938,18 @@ public static enum Kind { STORE, /** - * Increment local variable + * Increment local variable. * + * @see IncrementInstruction * @see Opcode#IINC * @see Opcode#IINC_W */ INCREMENT, /** - * Branch + * Branch. * + * @see BranchInstruction * @see Opcode#IFEQ * @see Opcode#IFNE * @see Opcode#IFLT @@ -804,22 +1972,25 @@ public static enum Kind { BRANCH, /** - * Access jump table by key match and jump + * Access jump table by key match and jump. * + * @see LookupSwitchInstruction * @see Opcode#LOOKUPSWITCH */ LOOKUP_SWITCH, /** - * Access jump table by index and jump + * Access jump table by index and jump. * + * @see TableSwitchInstruction * @see Opcode#TABLESWITCH */ TABLE_SWITCH, /** - * Return from method + * Return from method. * + * @see ReturnInstruction * @see Opcode#IRETURN * @see Opcode#LRETURN * @see Opcode#FRETURN @@ -830,15 +2001,17 @@ public static enum Kind { RETURN, /** - * Throw exception or error + * Throw exception or error. * + * @see ThrowInstruction * @see Opcode#ATHROW */ THROW_EXCEPTION, /** - * Access field + * Access field. * + * @see FieldInstruction * @see Opcode#GETSTATIC * @see Opcode#PUTSTATIC * @see Opcode#GETFIELD @@ -847,8 +2020,9 @@ public static enum Kind { FIELD_ACCESS, /** - * Invoke method or constructor + * Invoke method or constructor. * + * @see InvokeInstruction * @see Opcode#INVOKEVIRTUAL * @see Opcode#INVOKESPECIAL * @see Opcode#INVOKESTATIC @@ -857,51 +2031,58 @@ public static enum Kind { INVOKE, /** - * Invoke a dynamically-computed call site + * Invoke a dynamically-computed call site. * + * @see InvokeDynamicInstruction * @see Opcode#INVOKEDYNAMIC */ INVOKE_DYNAMIC, /** - * Create new object + * Create new object. * + * @see NewObjectInstruction * @see Opcode#NEW */ NEW_OBJECT, /** - * Create new array + * Create new array. * + * @see NewPrimitiveArrayInstruction * @see Opcode#NEWARRAY */ NEW_PRIMITIVE_ARRAY, /** - * Create new reference array + * Create new {@link TypeKind#REFERENCE reference} array. * + * @see NewReferenceArrayInstruction * @see Opcode#ANEWARRAY */ NEW_REF_ARRAY, /** - * Create new multidimensional array + * Create new multidimensional array. * + * @see NewMultiArrayInstruction * @see Opcode#MULTIANEWARRAY */ NEW_MULTI_ARRAY, /** - * Check whether object is of given type + * Check whether object is of given type. * + * @see TypeCheckInstruction * @see Opcode#CHECKCAST * @see Opcode#INSTANCEOF */ TYPE_CHECK, /** - * Load from array + * Load from array. * + * @see ArrayLoadInstruction * @see Opcode#IALOAD * @see Opcode#LALOAD * @see Opcode#FALOAD @@ -914,8 +2095,9 @@ public static enum Kind { ARRAY_LOAD, /** - * Store into array + * Store into array. * + * @see ArrayStoreInstruction * @see Opcode#IASTORE * @see Opcode#LASTORE * @see Opcode#FASTORE @@ -928,8 +2110,9 @@ public static enum Kind { ARRAY_STORE, /** - * Stack operations + * Stack operations. * + * @see StackInstruction * @see Opcode#POP * @see Opcode#POP2 * @see Opcode#DUP @@ -943,8 +2126,9 @@ public static enum Kind { STACK, /** - * Type conversions + * Type conversions. * + * @see ConvertInstruction * @see Opcode#I2L * @see Opcode#I2F * @see Opcode#I2D @@ -964,8 +2148,9 @@ public static enum Kind { CONVERT, /** - * Operators + * Operators. * + * @see OperatorInstruction * @see Opcode#IADD * @see Opcode#LADD * @see Opcode#FADD @@ -1012,8 +2197,9 @@ public static enum Kind { OPERATOR, /** - * Constants + * Constants. * + * @see ConstantInstruction * @see Opcode#ACONST_NULL * @see Opcode#ICONST_M1 * @see Opcode#ICONST_0 @@ -1038,35 +2224,37 @@ public static enum Kind { CONSTANT, /** - * Monitor + * Monitor. * + * @see MonitorInstruction * @see Opcode#MONITORENTER * @see Opcode#MONITOREXIT */ MONITOR, /** - * Do nothing + * Do nothing. * + * @see NopInstruction * @see Opcode#NOP */ NOP, /** - * Discontinued jump subroutine + * Discontinued jump subroutine. * + * @see DiscontinuedInstruction.JsrInstruction * @see Opcode#JSR * @see Opcode#JSR_W - * @see java.lang.classfile.instruction.DiscontinuedInstruction */ DISCONTINUED_JSR, /** - * Discontinued return from subroutine + * Discontinued return from subroutine. * + * @see DiscontinuedInstruction.RetInstruction * @see Opcode#RET * @see Opcode#RET_W - * @see java.lang.classfile.instruction.DiscontinuedInstruction */ DISCONTINUED_RET; } @@ -1090,7 +2278,10 @@ public static enum Kind { /** * {@return true if this is a pseudo-opcode modified by wide opcode} + *

    + * {@code wide} extends local variable index by additional bytes. * + * @jvms 6.5.wide wide * @see #ILOAD_W * @see #LLOAD_W * @see #FLOAD_W @@ -1109,11 +2300,14 @@ public static enum Kind { /** * {@return size of the instruction in bytes if fixed, or -1 otherwise} This size includes * the opcode itself. + * + * @see Instruction#sizeInBytes() Instruction::sizeInBytes */ public int sizeIfFixed() { return sizeIfFixed; } /** - * {@return instruction kind} + * {@return operation kind} Each kind of operation has its own modeling + * interface to model instructions belonging to that kind. */ public Kind kind() { return kind; } } diff --git a/src/java.base/share/classes/java/lang/classfile/TypeKind.java b/src/java.base/share/classes/java/lang/classfile/TypeKind.java index 5a6475aa801..e3fc11858f5 100644 --- a/src/java.base/share/classes/java/lang/classfile/TypeKind.java +++ b/src/java.base/share/classes/java/lang/classfile/TypeKind.java @@ -26,6 +26,9 @@ package java.lang.classfile; import java.lang.classfile.instruction.DiscontinuedInstruction; +import java.lang.classfile.instruction.LoadInstruction; +import java.lang.classfile.instruction.NewPrimitiveArrayInstruction; +import java.lang.classfile.instruction.StoreInstruction; import java.lang.constant.ClassDesc; import java.lang.constant.ConstantDescs; import java.lang.invoke.TypeDescriptor; @@ -33,13 +36,17 @@ import jdk.internal.vm.annotation.Stable; /** - * Describes the data types Java Virtual Machine operates on. - * This omits {@code returnAddress} (JVMS {@jvms 2.3.3}), - * which is only used by discontinued {@link - * DiscontinuedInstruction.JsrInstruction jsr} and {@link - * DiscontinuedInstruction.RetInstruction ret} instructions, - * and includes {@link #VOID void} (JVMS {@jvms 4.3.3}), which - * appears as a method return type. + * Describes the data types Java Virtual Machine operates on. This omits {@code + * returnAddress} (JVMS {@jvms 2.3.3}) and includes {@link #VOID void} (JVMS + * {@jvms 4.3.3}), which appears as a method return type. + *

    + * The {@index returnAddress} type is only used by discontinued + * {@linkplain DiscontinuedInstruction.JsrInstruction jump subroutine} and + * {@linkplain DiscontinuedInstruction.RetInstruction return from subroutine} + * instructions. Jump subroutine instructions push {@code returnAddress} to the + * operand stack; {@link StoreInstruction astore} instructions store {@code + * returnAddress} from the operand stack to local variables; return from + * subroutine instructions load {@code returnAddress} from local variables. * *

    Computational Type

    * In the {@code class} file format, local variables (JVMS {@jvms 2.6.1}), @@ -164,7 +171,10 @@ private ClassDesc fetchUpperBound() { /** * {@return the code used by the {@link Opcode#NEWARRAY newarray} instruction to create an array * of this component type, or {@code -1} if this type is not supported by {@code newarray}} - * @jvms 6.5.newarray newarray + * + * @jvms 6.5.newarray newarray + * @see NewPrimitiveArrayInstruction + * @see #fromNewarrayCode(int) fromNewarrayCode(int) */ public int newarrayCode() { return newarrayCode; @@ -175,6 +185,7 @@ public int newarrayCode() { * This is also the category of this type for instructions operating on the operand stack without * regard to type (JVMS {@jvms 2.11.1}), such as {@link Opcode#POP pop} versus {@link Opcode#POP2 * pop2}. + * * @jvms 2.6.1 Local Variables * @jvms 2.6.2 Operand Stacks */ @@ -185,6 +196,9 @@ public int slotSize() { /** * {@return the {@linkplain ##computational-type computational type} for this type, or {@link #VOID void} * for {@code void}} + * + * @see LoadInstruction + * @see StoreInstruction */ public TypeKind asLoadable() { return ordinal() < 4 ? INT : this; @@ -193,9 +207,12 @@ public TypeKind asLoadable() { /** * {@return the component type described by the array code used as an operand to {@link Opcode#NEWARRAY * newarray}} + * * @param newarrayCode the operand of the {@code newarray} instruction * @throws IllegalArgumentException if the code is invalid - * @jvms 6.5.newarray newarray + * @jvms 6.5.newarray newarray + * @see NewPrimitiveArrayInstruction + * @see #newarrayCode() newarrayCode() */ public static TypeKind fromNewarrayCode(int newarrayCode) { return switch (newarrayCode) { diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/AnnotationConstantValueEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/AnnotationConstantValueEntry.java index 5255ceb1ef7..c4b6546fe20 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/AnnotationConstantValueEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/AnnotationConstantValueEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,10 +28,9 @@ import java.lang.constant.ConstantDesc; /** - * A constant pool entry that may be used by annotation constant values, - * which includes the four kinds of primitive constants and UTF8 constants. - * These entries are also the only entries that do not refer to other - * constant pool entries. + * Marker interface for constant pool entries that can represent constant values + * associated with elements of annotations. They are also the only entries that + * do not refer to other constant pool entries. * * @apiNote * An annotation constant value entry alone is not sufficient to determine @@ -40,6 +39,7 @@ * in {@link AnnotationValue.OfInt}. * * @see AnnotationValue.OfConstant + * @jvms 4.7.16.1 The {@code element_value} structure * @sealedGraph * @since 24 */ @@ -47,9 +47,9 @@ public sealed interface AnnotationConstantValueEntry extends PoolEntry permits DoubleEntry, FloatEntry, IntegerEntry, LongEntry, Utf8Entry { /** - * {@return the constant value} The constant value will be an {@link Integer}, - * {@link Long}, {@link Float}, {@link Double} for the primitive constants, - * or {@link String} for UTF8 constants. + * {@return the constant value} The constant value will be an {@link + * Integer}, {@link Long}, {@link Float}, {@link Double} for the primitive + * constants, or {@link String} for UTF8 constants. */ ConstantDesc constantValue(); } diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/ClassEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/ClassEntry.java index 2a3bd95da22..5017838d68e 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/ClassEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/ClassEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,33 +30,82 @@ import jdk.internal.classfile.impl.AbstractPoolEntry; /** - * Models a {@code CONSTANT_Class_info} constant in the constant pool of a - * classfile. - * @jvms 4.4.1 The CONSTANT_Class_info Structure + * Models a {@code CONSTANT_Class_info} structure, representing a reference + * type, in the constant pool of a {@code class} file. + *

    + * The use of a {@code ClassEntry} is modeled by a {@link ClassDesc} that is not + * primitive. Conversions are through {@link ConstantPoolBuilder#classEntry( + * ClassDesc)} and {@link #asSymbol()}. + *

    + * A {@code ClassEntry} is composite: + * {@snippet lang=text : + * // @link substring="ClassEntry" target="ConstantPoolBuilder#classEntry(Utf8Entry)" : + * ClassEntry(Utf8Entry name) // @link substring="name" target="#name" + * } + * where {@code name} represents: + *

      + *
    • The internal form of a binary name (JVMS {@jvms 4.2.1}), if and only if + * this {@code ClassEntry} represents a class or interface, such as {@code + * java/lang/String} for the {@link String} class. + *
    • A field descriptor string (JVMS {@jvms 4.3.2}) representing an array type, + * if and only if this {@code ClassEntry} represents an array type, such as + * {@code [I} for the {@code int[]} type, or {@code [Ljava/lang/String;} for the + * {@code String[]} type. + *
    + * A field descriptor string for an array type can be distinguished by its + * leading {@code '['} character. * + * @apiNote + * The internal form of a binary name, where all occurrences of {@code .} in the + * name are replaced by {@code /}, is informally known as an {@index + * "internal name"}. This concept also applies to package names in + * addition to class and interface names. + * + * @see ConstantPoolBuilder#classEntry ConstantPoolBuilder::classEntry + * @see ClassDesc + * @jvms 4.4.1 The {@code CONSTANT_Class_info} Structure * @since 24 */ public sealed interface ClassEntry extends LoadableConstantEntry permits AbstractPoolEntry.ClassEntryImpl { + /** + * {@inheritDoc} + *

    + * This is equivalent to {@link #asSymbol() asSymbol()}. + */ @Override default ConstantDesc constantValue() { return asSymbol(); } /** - * {@return the UTF8 constant pool entry for the class name} + * {@return the {@code Utf8Entry} referred by this structure} If the + * value of the UTF8 starts with a {@code [}, this represents an array type + * and the value is a descriptor string; otherwise, this represents a class + * or interface and the value is the {@linkplain ##internalname internal + * form} of a binary name. + * + * @see ConstantPoolBuilder#classEntry(Utf8Entry) + * ConstantPoolBuilder::classEntry(Utf8Entry) */ Utf8Entry name(); /** - * {@return the class name, as an internal binary name} + * {@return the represented reference type, as the {@linkplain + * ##internalname internal form} of a binary name or an array descriptor + * string} This is a shortcut for {@link #name() name().stringValue()}. */ String asInternalName(); /** - * {@return the class name, as a symbolic descriptor} + * {@return the represented reference type, as a symbolic descriptor} The + * returned descriptor is never {@linkplain ClassDesc#isPrimitive() + * primitive}. + * + * @see ConstantPoolBuilder#classEntry(ClassDesc) + * ConstantPoolBuilder::classEntry(ClassDesc) */ ClassDesc asSymbol(); } diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantDynamicEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantDynamicEntry.java index 72050cd9b8f..bbd03c88292 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantDynamicEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantDynamicEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,10 +33,36 @@ import jdk.internal.classfile.impl.Util; /** - * Models a {@code CONSTANT_Dynamic_info} constant in the constant pool of a - * classfile. - * @jvms 4.4.10 The CONSTANT_Dynamic_info and CONSTANT_InvokeDynamic_info Structures + * Models a {@code CONSTANT_Dynamic_info} structure, representing a {@index + * "dynamically-computed constant"}, in the constant pool of a {@code + * class} file. + *

    + * The use of a {@code ConstantDynamicEntry} is modeled by a {@link + * DynamicConstantDesc}. Conversions are through {@link #asSymbol()} and {@link + * ConstantPoolBuilder#constantDynamicEntry(DynamicConstantDesc)}. + *

    + * A dynamic constant entry is composite: + * {@snippet lang=text : + * // @link substring="ConstantDynamicEntry" target="ConstantPoolBuilder#constantDynamicEntry(BootstrapMethodEntry, NameAndTypeEntry)" : + * ConstantDynamicEntry( + * BootstrapMethodEntry bootstrap, // @link substring="bootstrap" target="#bootstrap()" + * NameAndTypeEntry nameAndType // @link substring="nameAndType" target="#nameAndType()" + * ) + * } + * where {@link #type() nameAndType.type()} is a {@linkplain #typeSymbol() + * field descriptor} string. * + * @apiNote + * A dynamically-computed constant is frequently called a {@index "dynamic + * constant"}, or a {@index "condy"}, from the abbreviation of + * "constant dynamic". + * + * @see ConstantPoolBuilder#constantDynamicEntry + * ConstantPoolBuilder::constantDynamicEntry + * @see DynamicConstantDesc + * @see java.lang.invoke##condycon Dynamically-computed constants + * @jvms 4.4.10 The {@code CONSTANT_Dynamic_info} and {@code + * CONSTANT_InvokeDynamic_info} Structures * @since 24 */ public sealed interface ConstantDynamicEntry @@ -44,19 +70,28 @@ public sealed interface ConstantDynamicEntry permits AbstractPoolEntry.ConstantDynamicEntryImpl { /** - * {@return a symbolic descriptor for the dynamic constant's type} + * {@return a symbolic descriptor for the {@linkplain #type() field type} of + * this dynamically-computed constant} */ default ClassDesc typeSymbol() { return Util.fieldTypeSymbol(type()); } + /** + * {@inheritDoc} + *

    + * This is equivalent to {@link #asSymbol() asSymbol()}. + */ @Override default ConstantDesc constantValue() { return asSymbol(); } /** - * {@return the symbolic descriptor for the {@code invokedynamic} constant} + * {@return a symbolic descriptor for this dynamically-computed constant} + * + * @see ConstantPoolBuilder#constantDynamicEntry(DynamicConstantDesc) + * ConstantPoolBuilder::constantDynamicEntry(DynamicConstantDesc) */ default DynamicConstantDesc asSymbol() { return DynamicConstantDesc.ofNamed(bootstrap().bootstrapMethod().asSymbol(), @@ -68,10 +103,15 @@ default DynamicConstantDesc asSymbol() { } /** - * {@return the type of the constant} + * {@inheritDoc} + * + * @apiNote + * The data type of a dynamically-computed constant depends on its + * {@linkplain #type() descriptor}, while the data type of all other + * constants can be determined by their {@linkplain #tag() constant type}. */ @Override default TypeKind typeKind() { - return TypeKind.fromDescriptor(type().stringValue()); + return TypeKind.fromDescriptor(type()); } } diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPool.java b/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPool.java index 91dc8906b7b..6fed8dad8b7 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPool.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPool.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,14 +27,22 @@ import java.lang.classfile.BootstrapMethodEntry; import java.lang.classfile.ClassReader; +import java.lang.classfile.attribute.BootstrapMethodsAttribute; import java.util.Iterator; import java.util.NoSuchElementException; /** - * Provides read access to the constant pool and bootstrap method table of a - * classfile. - * @jvms 4.4 The Constant Pool + * Provides read access to the constant pool and the bootstrap method table of a + * {@code class} file. + * + *

    Index in the Constant Pool

    + * The constant pool entries are accessed by index. A valid index is in the + * range of {@link #size() [1, size())}. It is {@linkplain PoolEntry#width() + * unusable} if a {@link LongEntry} or {@link DoubleEntry} is at its previous + * index. * + * @see BootstrapMethodsAttribute + * @jvms 4.4 The Constant Pool * @sealedGraph * @since 24 */ @@ -46,7 +54,7 @@ public sealed interface ConstantPool extends Iterable * * @apiNote * If only a particular type of entry is expected, use {@link #entryByIndex( - * int, Class) entryByIndex(int, Class)}. + * int, Class)}. * * @param index the index within the pool of the desired entry * @throws ConstantPoolException if the index is out of range of the @@ -55,7 +63,11 @@ public sealed interface ConstantPool extends Iterable PoolEntry entryByIndex(int index); /** - * {@return the size of the constant pool} + * {@return the exclusive upper bound of the valid indices of this constant + * pool} The actual number of entries is lower because {@code 0}, {@code + * size()} are not valid, and a valid index may be unusable. + * + * @see ##index Index in the Constant Pool */ int size(); @@ -66,12 +78,17 @@ public sealed interface ConstantPool extends Iterable * @param index the index within the pool of the desired entry * @param cls the entry type * @throws ConstantPoolException if the index is out of range of the - * constant pool, or the entry is not of the given type + * constant pool or considered unusable, or the entry is not + * of the given type */ T entryByIndex(int index, Class cls); /** * {@return an iterator over pool entries} + * + * @apiNote + * This skips any unusable index and is less error-prone than iterating by + * raw index. See {@linkplain ##index Index in the Constant Pool}. */ @Override default Iterator iterator() { @@ -93,7 +110,6 @@ public PoolEntry next() { }; } - /** * {@return the {@link BootstrapMethodEntry} at the specified index within * the bootstrap method table} diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPoolBuilder.java b/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPoolBuilder.java index 2dc2a390bd1..260fc982dab 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPoolBuilder.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPoolBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,10 +25,16 @@ package java.lang.classfile.constantpool; import java.lang.classfile.BootstrapMethodEntry; -import java.lang.classfile.ClassBuilder; +import java.lang.classfile.ClassFile; +import java.lang.classfile.ClassFileBuilder; import java.lang.classfile.ClassModel; +import java.lang.classfile.CodeBuilder; +import java.lang.classfile.attribute.ConstantValueAttribute; +import java.lang.classfile.instruction.ConstantInstruction; import java.lang.constant.*; +import java.lang.invoke.MethodHandleInfo; import java.util.List; +import java.util.function.Consumer; import jdk.internal.classfile.impl.AbstractPoolEntry.ClassEntryImpl; import jdk.internal.classfile.impl.ClassReaderImpl; @@ -39,14 +45,45 @@ import static java.util.Objects.requireNonNull; /** - * Builder for the constant pool of a classfile. Provides read and write access - * to the constant pool that is being built. Writing is append-only and idempotent - * (entry-bearing methods will return an existing entry if there is one). + * Builder for the constant pool of a {@code class} file. Provides read and + * write access to the constant pool that is {@linkplain ClassFileBuilder#constantPool() + * being built}. Writing is append-only (the index of new entries monotonically + * increase) and idempotent (entry-bearing methods will return an existing entry + * if there is a suitable one). + *

    + * For {@code class} file building, an overload of {@link ClassFile#build( + * ClassEntry, ConstantPoolBuilder, Consumer) ClassFile::build} takes a + * {@code ConstantPoolBuilder}. For {@code class} file transformations via + * {@link ClassFile#transformClass ClassFile::transformClass}, the {@link + * ClassFile.ConstantPoolSharingOption} controls how the constant pool builder + * of the resulting {@code class} is created. * - * A {@linkplain ConstantPoolBuilder} is associated with a {@link ClassBuilder}. - * The {@linkplain ConstantPoolBuilder} also provides access to some of the - * state of the {@linkplain ClassBuilder}, such as classfile processing options. + *

    Alien Constant Pool Entries

    + * In {@code class} file building and constant pool building, some constant pool + * entries supplied may be {@linkplain #canWriteDirect(ConstantPool) alien} + * to this constant pool builder of the active class file builder. For example, + * {@link #classEntry(Utf8Entry) classEntry(Utf8Entry)} may be called with an + * alien UTF8 entry. Alien entries will be converted to a pool entry in + * this constant pool builder, reusing equivalent entries or adding new entries + * if there is none. As a result, all pool entries returned by entry-bearing + * methods in this constant pool builder belong to this constant pool. + *

    + * Some {@link ClassFileBuilder} methods may have their outputs adjusted if they + * receive pool entries alien to {@linkplain ClassFileBuilder#constantPool + * their constant pools}. For example, if an {@link ConstantInstruction#ofLoad + * ldc_w} instruction with an alien entry is written to a {@link CodeBuilder}, + * the {@code CodeBuilder} may emit a functionally equivalent {@code ldc} + * instruction instead, if the converted entry can be encoded in such an + * instruction. + *

    + * To avoid the conversion of alien constant pool entries, such as for the + * accuracy of the generated {@code class} file, users can always supply + * constant pool entries obtained by calling the constant pool builder + * entry-bearing methods of the constant pools associated with the {@code + * ClassFileBuilder}. Otherwise, the conversions have no impact on the + * behaviors of the generated {@code class} files. * + * @see ClassFileBuilder#constantPool() * @since 24 */ public sealed interface ConstantPoolBuilder @@ -55,10 +92,14 @@ public sealed interface ConstantPoolBuilder /** * {@return a new constant pool builder} The new constant pool builder will - * be pre-populated with the contents of the constant pool associated with - * the class reader. + * be pre-populated with the contents of the constant pool {@linkplain + * ClassModel#constantPool() associated with} the given class model. The + * index of new entries will start from the {@link ConstantPool#size() + * size()} of the source pool. * * @param classModel the class to copy from + * @see ClassFile#build(ClassEntry, ConstantPoolBuilder, Consumer) + * @see ClassFile.ConstantPoolSharingOption#SHARED_POOL */ static ConstantPoolBuilder of(ClassModel classModel) { return new SplitConstantPool((ClassReaderImpl) classModel.constantPool()); @@ -66,35 +107,47 @@ static ConstantPoolBuilder of(ClassModel classModel) { /** * {@return a new constant pool builder} The new constant pool builder - * will be empty. + * will be empty. The index of new entries will start from {@code 1}. + * + * @see ClassFile.ConstantPoolSharingOption#NEW_POOL */ static ConstantPoolBuilder of() { return new SplitConstantPool(); } /** - * {@return whether the provided constant pool is index-compatible with this - * one} This may be because they are the same constant pool, or because this - * constant pool was copied from the other. + * {@return {@code true} if the index of any entry in the given constant + * pool refers to the same entry in this builder} This may be because they + * are the same builder, or because this builder was {@linkplain + * #of(ClassModel) pre-populated} from the given constant pool. + *

    + * If the constant pool of an entry is not directly writable to this pool, + * it is alien to this pool, and a {@link ClassFileBuilder} associated + * with this constant pool will convert that alien constant pool entry. * - * @param constantPool the other constant pool + * @param constantPool the given constant pool + * @see ClassFileBuilder#constantPool() ClassFileBuilder::constantPool + * @see ##alien Alien Constant Pool Entries */ boolean canWriteDirect(ConstantPool constantPool); /** - * {@return A {@link Utf8Entry} describing the provided {@linkplain String}} - * If a UTF8 entry in the pool already describes this string, it is returned; - * otherwise, a new entry is added and the new entry is returned. + * {@return a {@link Utf8Entry} describing the provided {@link String}} * * @param s the string + * @see Utf8Entry#stringValue() Utf8Entry::stringValue */ Utf8Entry utf8Entry(String s); /** - * {@return A {@link Utf8Entry} describing the field descriptor of the provided - * {@linkplain ClassDesc}} - * If a UTF8 entry in the pool already describes this field descriptor, it is returned; - * otherwise, a new entry is added and the new entry is returned. + * {@return a {@link Utf8Entry} describing the {@linkplain + * ClassDesc#descriptorString() field descriptor string} of the provided + * {@link ClassDesc}} + * + * @apiNote + * The resulting {@code Utf8Entry} is usually not {@linkplain + * #classEntry(Utf8Entry) referable by} a {@link ClassEntry}, which uses + * internal form of binary names. * * @param desc the symbolic descriptor for the class */ @@ -103,10 +156,9 @@ default Utf8Entry utf8Entry(ClassDesc desc) { } /** - * {@return A {@link Utf8Entry} describing the method descriptor of the provided - * {@linkplain MethodTypeDesc}} - * If a UTF8 entry in the pool already describes this field descriptor, it is returned; - * otherwise, a new entry is added and the new entry is returned. + * {@return a {@link Utf8Entry} describing the {@linkplain + * MethodTypeDesc#descriptorString() method descriptor string} of the + * provided {@link MethodTypeDesc}} * * @param desc the symbolic descriptor for the method type */ @@ -115,25 +167,24 @@ default Utf8Entry utf8Entry(MethodTypeDesc desc) { } /** - * {@return A {@link ClassEntry} describing the class whose internal name - * is encoded in the provided {@linkplain Utf8Entry}} - * If a Class entry in the pool already describes this class, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return a {@link ClassEntry} referring to the provided {@link + * Utf8Entry}} The {@code Utf8Entry} describes the internal form + * of the binary name of a class or interface or the field descriptor + * string of an array type. * - * @param ne the constant pool entry describing the internal name of the class + * @param ne the {@code Utf8Entry} + * @see ClassEntry#name() ClassEntry::name */ ClassEntry classEntry(Utf8Entry ne); /** - * {@return A {@link ClassEntry} describing the class described by - * provided {@linkplain ClassDesc}} - * If a Class entry in the pool already describes this class, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return a {@link ClassEntry} describing the same reference type + * as the provided {@link ClassDesc}} * - * @param classDesc the symbolic descriptor for the class - * @throws IllegalArgumentException if {@code classDesc} represents a primitive type + * @param classDesc the symbolic descriptor for the reference type + * @throws IllegalArgumentException if {@code classDesc} represents a + * primitive type + * @see ClassEntry#asSymbol() ClassEntry::asSymbol */ default ClassEntry classEntry(ClassDesc classDesc) { if (requireNonNull(classDesc).isPrimitive()) { @@ -145,196 +196,191 @@ default ClassEntry classEntry(ClassDesc classDesc) { } /** - * {@return A {@link PackageEntry} describing the class whose internal name - * is encoded in the provided {@linkplain Utf8Entry}} - * If a Package entry in the pool already describes this class, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return a {@link PackageEntry} referring to the provided {@link + * Utf8Entry}} The {@code Utf8Entry} describes the internal form + * of the name of a package. * - * @param nameEntry the constant pool entry describing the internal name of - * the package + * @param nameEntry the {@code Utf8Entry} + * @see PackageEntry#name() PackageEntry::name */ PackageEntry packageEntry(Utf8Entry nameEntry); /** - * {@return A {@link PackageEntry} describing the class described by - * provided {@linkplain PackageDesc}} - * If a Package entry in the pool already describes this class, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return a {@link PackageEntry} describing the same package as the + * provided {@link PackageDesc}} * - * @param packageDesc the symbolic descriptor for the class + * @param packageDesc the symbolic descriptor for the package + * @see PackageEntry#asSymbol() PackageEntry::asSymbol */ default PackageEntry packageEntry(PackageDesc packageDesc) { return packageEntry(utf8Entry(packageDesc.internalName())); } /** - * {@return A {@link ModuleEntry} describing the module whose name - * is encoded in the provided {@linkplain Utf8Entry}} - * If a module entry in the pool already describes this class, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return a {@link ModuleEntry} referring to the provided {@link + * Utf8Entry}} The {@code Utf8Entry} describes the module name. * * @param moduleName the constant pool entry describing the module name + * @see ModuleEntry#name() ModuleEntry::name */ ModuleEntry moduleEntry(Utf8Entry moduleName); /** - * {@return A {@link ModuleEntry} describing the module described by - * provided {@linkplain ModuleDesc}} - * If a module entry in the pool already describes this class, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return a {@link ModuleEntry} describing the same module as the provided + * {@link ModuleDesc}} * - * @param moduleDesc the symbolic descriptor for the class + * @param moduleDesc the symbolic descriptor for the module + * @see ModuleEntry#asSymbol() ModuleEntry::asSymbol */ default ModuleEntry moduleEntry(ModuleDesc moduleDesc) { return moduleEntry(utf8Entry(moduleDesc.name())); } /** - * {@return A {@link NameAndTypeEntry} describing the provided name and type} - * If a NameAndType entry in the pool already describes this name and type, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return a {@link NameAndTypeEntry} referring to the provided name and + * type {@link Utf8Entry}} The name {@code Utf8Entry} describes an + * unqualified name or the special name {@value ConstantDescs#INIT_NAME}, + * and the type {@code Utf8Entry} describes a field or method descriptor + * string. * - * @param nameEntry the member name - * @param typeEntry the member field or method descriptor + * @param nameEntry the name {@code Utf8Entry} + * @param typeEntry the type {@code Utf8Entry} + * @see NameAndTypeEntry#name() NameAndTypeEntry::name + * @see NameAndTypeEntry#type() NameAndTypeEntry::type */ NameAndTypeEntry nameAndTypeEntry(Utf8Entry nameEntry, Utf8Entry typeEntry); /** - * {@return A {@link NameAndTypeEntry} describing the provided name and type} - * If a NameAndType entry in the pool already describes this name and type, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return a {@link NameAndTypeEntry} describing the provided unqualified + * name and field descriptor} * - * @param name the member name - * @param type the symbolic descriptor for a field type + * @param name the unqualified name + * @param type the field descriptor */ default NameAndTypeEntry nameAndTypeEntry(String name, ClassDesc type) { return nameAndTypeEntry(utf8Entry(name), utf8Entry(type)); } /** - * {@return A {@link NameAndTypeEntry} describing the provided name and type} - * If a NameAndType entry in the pool already describes this name and type, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return a {@link NameAndTypeEntry} describing the provided name and + * method descriptor} The name can be an unqualified name or the + * special name {@value ConstantDescs#INIT_NAME}. * - * @param name the member name - * @param type the symbolic descriptor for a method type + * @param name the unqualified name, or {@value ConstantDescs#INIT_NAME} + * @param type the method descriptor */ default NameAndTypeEntry nameAndTypeEntry(String name, MethodTypeDesc type) { return nameAndTypeEntry(utf8Entry(name), utf8Entry(type)); } /** - * {@return A {@link FieldRefEntry} describing a field of a class} - * If a FieldRef entry in the pool already describes this field, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return a {@link FieldRefEntry} referring to a {@link ClassEntry} and a + * {@link NameAndTypeEntry}} The {@code ClassEntry} describes a class or + * interface that has this field as a member, and the {@code + * NameAndTypeEntry} describes the unqualified name and the field descriptor + * for this field. * - * @param owner the class the field is a member of - * @param nameAndType the name and type of the field + * @param owner the {@code ClassEntry} + * @param nameAndType the {@code NameAndTypeEntry} + * @see FieldRefEntry#owner() FieldRefEntry::owner + * @see FieldRefEntry#nameAndType() FieldRefEntry::nameAndType */ FieldRefEntry fieldRefEntry(ClassEntry owner, NameAndTypeEntry nameAndType); /** - * {@return A {@link FieldRefEntry} describing a field of a class} - * If a FieldRef entry in the pool already describes this field, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return a {@link FieldRefEntry} describing a field of a class} * - * @param owner the class the field is a member of - * @param name the name of the field - * @param type the type of the field + * @param owner the class or interface the field is a member of + * @param name the unqualified name of the field + * @param type the field descriptor * @throws IllegalArgumentException if {@code owner} represents a primitive type + * @see FieldRefEntry#typeSymbol() FieldRefEntry::typeSymbol */ default FieldRefEntry fieldRefEntry(ClassDesc owner, String name, ClassDesc type) { return fieldRefEntry(classEntry(owner), nameAndTypeEntry(name, type)); } /** - * {@return A {@link MethodRefEntry} describing a method of a class} - * If a MethodRefEntry entry in the pool already describes this method, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return a {@link MethodRefEntry} referring to a {@link ClassEntry} and a + * {@link NameAndTypeEntry}} The {@code ClassEntry} describes a class that + * has this method as a member, and the {@code NameAndTypeEntry} describes + * the unqualified name or the special name {@value ConstantDescs#INIT_NAME} + * and the method descriptor for this method. * - * @param owner the class the method is a member of - * @param nameAndType the name and type of the method + * @param owner the {@code ClassEntry} + * @param nameAndType the {@code NameAndTypeEntry} + * @see MethodRefEntry#owner() MethodRefEntry::owner + * @see MethodRefEntry#nameAndType() MethodRefEntry::nameAndType */ MethodRefEntry methodRefEntry(ClassEntry owner, NameAndTypeEntry nameAndType); /** - * {@return A {@link MethodRefEntry} describing a method of a class} - * If a MethodRefEntry entry in the pool already describes this method, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return a {@link MethodRefEntry} describing a method of a class} * * @param owner the class the method is a member of - * @param name the name of the method - * @param type the type of the method + * @param name the unqualified name, or special name {@value + * ConstantDescs#INIT_NAME}, of the method + * @param type the method descriptor * @throws IllegalArgumentException if {@code owner} represents a primitive type + * @see MethodRefEntry#typeSymbol() MethodRefEntry::typeSymbol */ default MethodRefEntry methodRefEntry(ClassDesc owner, String name, MethodTypeDesc type) { return methodRefEntry(classEntry(owner), nameAndTypeEntry(name, type)); } /** - * {@return A {@link InterfaceMethodRefEntry} describing a method of a class} - * If a InterfaceMethodRefEntry entry in the pool already describes this method, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return an {@link InterfaceMethodRefEntry} referring to a {@link + * ClassEntry} and a {@link NameAndTypeEntry}} The {@code ClassEntry} + * describes an interface that has this method as a member, and the {@code + * NameAndTypeEntry} describes the unqualified name and the method + * descriptor for this method. * - * @param owner the class the method is a member of - * @param nameAndType the name and type of the method + * @param owner the {@code ClassEntry} + * @param nameAndType the {@code NameAndTypeEntry} + * @see InterfaceMethodRefEntry#owner() InterfaceMethodRefEntry::owner + * @see InterfaceMethodRefEntry#nameAndType() + * InterfaceMethodRefEntry::nameAndType */ InterfaceMethodRefEntry interfaceMethodRefEntry(ClassEntry owner, NameAndTypeEntry nameAndType); /** - * {@return A {@link InterfaceMethodRefEntry} describing a method of a class} - * If a InterfaceMethodRefEntry entry in the pool already describes this method, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return an {@link InterfaceMethodRefEntry} describing a method of an + * interface} * - * @param owner the class the method is a member of - * @param name the name of the method - * @param type the type of the method + * @param owner the interface the method is a member of + * @param name the unqualified name of the method + * @param type the method descriptor * @throws IllegalArgumentException if {@code owner} represents a primitive type + * @see InterfaceMethodRefEntry#typeSymbol() InterfaceMethodRefEntry::typeSymbol */ default InterfaceMethodRefEntry interfaceMethodRefEntry(ClassDesc owner, String name, MethodTypeDesc type) { return interfaceMethodRefEntry(classEntry(owner), nameAndTypeEntry(name, type)); } /** - * {@return A {@link MethodTypeEntry} describing a method type} - * If a MethodType entry in the pool already describes this method type, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return a {@link MethodTypeEntry} describing the same method type as + * the provided {@link MethodTypeDesc}} * * @param descriptor the symbolic descriptor of the method type + * @see MethodTypeEntry#asSymbol() MethodTypeEntry::asSymbol */ MethodTypeEntry methodTypeEntry(MethodTypeDesc descriptor); /** - * {@return A {@link MethodTypeEntry} describing a method type} - * If a MethodType entry in the pool already describes this method type, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return a {@link MethodTypeEntry} referring to a {@link Utf8Entry}} + * The {@code Utf8Entry} represents a method descriptor string. * - * @param descriptor the constant pool entry for the method type descriptor + * @param descriptor the {@code Utf8Entry} + * @see MethodTypeEntry#descriptor() MethodTypeEntry::descriptor */ MethodTypeEntry methodTypeEntry(Utf8Entry descriptor); /** - * {@return A {@link MethodHandleEntry} describing a direct method handle} - * If a MethodHandle entry in the pool already describes this method handle, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return a {@link MethodHandleEntry} describing the same method handle as + * the given {@link DirectMethodHandleDesc}} * * @param descriptor the symbolic descriptor of the method handle + * @see MethodHandleEntry#asSymbol() MethodHandleEntry::asSymbol */ default MethodHandleEntry methodHandleEntry(DirectMethodHandleDesc descriptor) { var owner = classEntry(descriptor.owner()); @@ -347,125 +393,133 @@ default MethodHandleEntry methodHandleEntry(DirectMethodHandleDesc descriptor) { } /** - * {@return A {@link MethodHandleEntry} describing a field accessor or method} - * If a MethodHandle entry in the pool already describes this method handle, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return a {@link MethodHandleEntry} encoding a reference kind and + * referring to a {@link MemberRefEntry}} The reference kind must be + * in {@code [1, 9]}, and the {@code MemberRefEntry} is subject to + * various restrictions based on the reference kind (JVMS {@jvms 4.4.8}). * - * @param refKind the reference kind of the method handle (JVMS {@jvms 4.4.8}) - * @param reference the constant pool entry describing the field or method + * @param refKind the reference kind of the method handle + * @param reference the {@code MemberRefEntry} + * @see MethodHandleInfo##refkinds Reference kinds + * @see MethodHandleEntry#kind() MethodHandleEntry::kind + * @see MethodHandleEntry#reference() MethodHandleEntry::reference */ MethodHandleEntry methodHandleEntry(int refKind, MemberRefEntry reference); /** - * {@return An {@link InvokeDynamicEntry} describing a dynamic call site} - * If an InvokeDynamic entry in the pool already describes this site, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return an {@link InvokeDynamicEntry} describing the same dynamic call + * site as the provided {@link DynamicCallSiteDesc}} * - * @param dcsd the symbolic descriptor of the method handle + * @param dcsd the symbolic descriptor of the dynamic call site + * @see InvokeDynamicEntry#asSymbol() InvokeDynamicEntry::asSymbol */ default InvokeDynamicEntry invokeDynamicEntry(DynamicCallSiteDesc dcsd) { return invokeDynamicEntry(bsmEntry((DirectMethodHandleDesc)dcsd.bootstrapMethod(), List.of(dcsd.bootstrapArgs())), nameAndTypeEntry(dcsd.invocationName(), dcsd.invocationType())); } /** - * {@return An {@link InvokeDynamicEntry} describing a dynamic call site} - * If an InvokeDynamic entry in the pool already describes this site, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return an {@link InvokeDynamicEntry} referring to a {@link + * BootstrapMethodEntry} and a {@link NameAndTypeEntry}} + * The {@code BootstrapMethodEntry} describes the bootstrap method + * and its invocation arguments in addition to the name and type, + * and the {@code NameAndTypeEntry} a name and a method descriptor. * - * @param bootstrapMethodEntry the entry in the bootstrap method table - * @param nameAndType the invocation name and type + * @param bootstrapMethodEntry the {@code BootstrapMethodEntry} + * @param nameAndType the {@code NameAndTypeEntry} + * @see InvokeDynamicEntry#bootstrap() InvokeDynamicEntry::bootstrap + * @see InvokeDynamicEntry#nameAndType() InvokeDynamicEntry::nameAndType */ InvokeDynamicEntry invokeDynamicEntry(BootstrapMethodEntry bootstrapMethodEntry, NameAndTypeEntry nameAndType); /** - * {@return A {@link ConstantDynamicEntry} describing a dynamic constant} - * If a ConstantDynamic entry in the pool already describes this site, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return a {@link ConstantDynamicEntry} describing the dynamic constant + * as the provided {@link DynamicConstantDesc}} * * @param dcd the symbolic descriptor of the constant + * @see ConstantDynamicEntry#asSymbol() ConstantDynamicEntry::asSymbol */ default ConstantDynamicEntry constantDynamicEntry(DynamicConstantDesc dcd) { return constantDynamicEntry(bsmEntry(dcd.bootstrapMethod(), List.of(dcd.bootstrapArgs())), nameAndTypeEntry(dcd.constantName(), dcd.constantType())); } /** - * {@return A {@link ConstantDynamicEntry} describing a dynamic constant} - * If a ConstantDynamic entry in the pool already describes this site, - * it is returned; otherwise, a new entry is added and the new entry is - * returned. + * {@return a {@link ConstantDynamicEntry} referring to a {@link + * BootstrapMethodEntry} and a {@link NameAndTypeEntry}} + * The {@code BootstrapMethodEntry} describes the bootstrap method + * and its invocation arguments in addition to the name and type, + * and the {@code NameAndTypeEntry} a name and a field descriptor. * - * @param bootstrapMethodEntry the entry in the bootstrap method table - * @param nameAndType the invocation name and type + * @param bootstrapMethodEntry the {@code BootstrapMethodEntry} + * @param nameAndType the {@code NameAndTypeEntry} + * @see ConstantDynamicEntry#bootstrap() ConstantDynamicEntry::bootstrap + * @see ConstantDynamicEntry#nameAndType() ConstantDynamicEntry::nameAndType */ ConstantDynamicEntry constantDynamicEntry(BootstrapMethodEntry bootstrapMethodEntry, NameAndTypeEntry nameAndType); /** - * {@return An {@link IntegerEntry} describing the provided value} - * If an integer entry in the pool already describes this value, it is returned; - * otherwise, a new entry is added and the new entry is returned. + * {@return an {@link IntegerEntry} describing the provided value} * * @param value the value + * @see IntegerEntry#intValue() IntegerEntry::intValue */ IntegerEntry intEntry(int value); /** - * {@return A {@link FloatEntry} describing the provided value} - * If a float entry in the pool already describes this value, it is returned; - * otherwise, a new entry is added and the new entry is returned. + * {@return a {@link FloatEntry} describing the provided value} * * @param value the value + * @see FloatEntry#floatValue() FloatEntry::floatValue */ FloatEntry floatEntry(float value); /** - * {@return A {@link LongEntry} describing the provided value} - * If a long entry in the pool already describes this value, it is returned; - * otherwise, a new entry is added and the new entry is returned. + * {@return a {@link LongEntry} describing the provided value} * * @param value the value + * @see LongEntry#longValue() LongEntry::longValue */ LongEntry longEntry(long value); /** - * {@return A {@link DoubleEntry} describing the provided value} - * If a double entry in the pool already describes this value, it is returned; - * otherwise, a new entry is added and the new entry is returned. + * {@return a {@link DoubleEntry} describing the provided value} * * @param value the value + * @see DoubleEntry#doubleValue() DoubleEntry::doubleValue */ DoubleEntry doubleEntry(double value); /** - * {@return A {@link StringEntry} referencing the provided UTF8 entry} - * If a String entry in the pool already describes this value, it is returned; - * otherwise, a new entry is added and the new entry is returned. + * {@return a {@link StringEntry} referring to a {@link Utf8Entry}} + * The {@code Utf8Entry} describes the string value. * - * @param utf8 the UTF8 entry describing the string + * @param utf8 the {@code Utf8Entry} + * @see StringEntry#utf8() StringEntry::utf8 */ StringEntry stringEntry(Utf8Entry utf8); /** - * {@return A {@link StringEntry} describing the provided value} - * If a string entry in the pool already describes this value, it is returned; - * otherwise, a new entry is added and the new entry is returned. + * {@return a {@link StringEntry} describing the provided value} * * @param value the value + * @see StringEntry#stringValue() StringEntry::stringValue */ default StringEntry stringEntry(String value) { return stringEntry(utf8Entry(value)); } /** - * {@return A {@link ConstantValueEntry} describing the provided - * Integer, Long, Float, Double, or String constant} + * {@return a {@link ConstantValueEntry} describing the provided constant + * {@link Integer}, {@link Long}, {@link Float}, {@link Double}, or {@link + * String} value} * - * @param c the constant - * @see ConstantValueEntry#constantValue() + * @param c the provided constant value + * @throws IllegalArgumentException if the value is not one of {@code + * Integer}, {@code Long}, {@code Float}, {@code Double}, or {@code + * String} + * @see ConstantValueEntry#constantValue() ConstantValueEntry::constantValue + * @see ConstantValueAttribute#of(ConstantDesc) + * ConstantValueAttribute::of(ConstantDesc) */ default ConstantValueEntry constantValueEntry(ConstantDesc c) { if (c instanceof Integer i) return intEntry(i); @@ -477,13 +531,10 @@ default ConstantValueEntry constantValueEntry(ConstantDesc c) { } /** - * {@return A {@link LoadableConstantEntry} describing the provided - * constant} The constant should be an Integer, String, Long, Float, - * Double, ClassDesc (for a Class constant), MethodTypeDesc (for a MethodType - * constant), DirectMethodHandleDesc (for a MethodHandle constant), or - * a DynamicConstantDesc (for a dynamic constant.) + * {@return a {@link LoadableConstantEntry} describing the provided constant + * value} * - * @param c the constant + * @param c the nominal descriptor for the constant */ default LoadableConstantEntry loadableConstantEntry(ConstantDesc c) { if (c instanceof Integer i) return intEntry(i); @@ -500,10 +551,10 @@ default LoadableConstantEntry loadableConstantEntry(ConstantDesc c) { /** * {@return a {@link BootstrapMethodEntry} describing the provided - * bootstrap method and static arguments} + * bootstrap method and arguments} * * @param methodReference the bootstrap method - * @param arguments the bootstrap arguments + * @param arguments the arguments */ default BootstrapMethodEntry bsmEntry(DirectMethodHandleDesc methodReference, List arguments) { @@ -512,11 +563,16 @@ default BootstrapMethodEntry bsmEntry(DirectMethodHandleDesc methodReference, } /** - * {@return a {@link BootstrapMethodEntry} describing the provided - * bootstrap method and static arguments} + * {@return a {@link BootstrapMethodEntry} referring to a {@link + * MethodHandleEntry} and a list of {@link LoadableConstantEntry}} + * The {@code MethodHandleEntry} is the bootstrap method, and the + * list of {@code LoadableConstantEntry} is the arguments. * - * @param methodReference the bootstrap method - * @param arguments the bootstrap arguments + * @param methodReference the {@code MethodHandleEntry} + * @param arguments the list of {@code LoadableConstantEntry} + * @see BootstrapMethodEntry#bootstrapMethod() + * BootstrapMethodEntry::bootstrapMethod + * @see BootstrapMethodEntry#arguments() BootstrapMethodEntry::arguments */ BootstrapMethodEntry bsmEntry(MethodHandleEntry methodReference, List arguments); diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPoolException.java b/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPoolException.java index ce5ed26c4c9..bb3b33ba21c 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPoolException.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPoolException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,9 @@ /** * Thrown to indicate that requested entry cannot be obtained from the constant - * pool. + * pool or the bootstrap method table. This is also thrown when the lazy + * evaluation of constant pool or bootstrap method table entries encounter + * format errors. * * @since 24 */ @@ -47,7 +49,8 @@ public ConstantPoolException() { * Constructs a {@code ConstantPoolException} with the specified detail * message. * - * @param message the detail message. + * @param message the detail message, may be {@code null} for no detail + * message */ public ConstantPoolException(String message) { super(message); @@ -55,11 +58,10 @@ public ConstantPoolException(String message) { /** * Constructs a {@code ConstantPoolException} with the specified cause and - * a detail message of {@code (cause==null ? null : cause.toString())}. - * @param cause the cause (which is saved for later retrieval by the - * {@link Throwable#getCause()} method). (A {@code null} value is - * permitted, and indicates that the cause is nonexistent or - * unknown.) + * a detail message of {@code cause == null ? null : cause.toString()}. + * + * @param cause the cause, may be {@code null} for nonexistent or unknown + * cause */ public ConstantPoolException(Throwable cause) { super(cause); @@ -69,12 +71,10 @@ public ConstantPoolException(Throwable cause) { * Constructs a {@code ConstantPoolException} with the specified detail * message and cause. * - * @param message the detail message (which is saved for later retrieval - * by the {@link Throwable#getMessage()} method). - * @param cause the cause (which is saved for later retrieval by the - * {@link Throwable#getCause()} method). (A {@code null} value - * is permitted, and indicates that the cause is nonexistent or - * unknown.) + * @param message the detail message, may be {@code null} for no detail + * message + * @param cause the cause, may be {@code null} for nonexistent or unknown + * cause */ public ConstantPoolException(String message, Throwable cause) { super(message, cause); diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantValueEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantValueEntry.java index ae746042aa4..8613fdd2cb9 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantValueEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantValueEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,10 +28,11 @@ import java.lang.constant.ConstantDesc; /** - * Models a constant pool entry that can be used as the constant in a - * {@link Attributes#constantValue() ConstantValue} attribute; this includes the four - * primitive constant types and {@linkplain String} constants. + * Marker interface for constant pool entries that can represent constant values + * in the {@link Attributes#constantValue() ConstantValue} attribute. * + * @see ConstantPoolBuilder#constantValueEntry + * ConstantPoolBuilder::constantValueEntry * @sealedGraph * @since 24 */ @@ -39,8 +40,8 @@ public sealed interface ConstantValueEntry extends LoadableConstantEntry permits DoubleEntry, FloatEntry, IntegerEntry, LongEntry, StringEntry { /** - * {@return the constant value} The constant value will be an {@link Integer}, - * {@link Long}, {@link Float}, {@link Double}, or {@link String}. + * {@return the constant value} The constant value will be an {@link + * Integer}, {@link Long}, {@link Float}, {@link Double}, or {@link String}. * * @see ConstantPoolBuilder#constantValueEntry(ConstantDesc) */ diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/DoubleEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/DoubleEntry.java index ebc3a837bb0..bc6956b5bf5 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/DoubleEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/DoubleEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,10 +29,20 @@ import jdk.internal.classfile.impl.AbstractPoolEntry; /** - * Models a {@code CONSTANT_Double_info} constant in the constant pool of a - * classfile. - * @jvms 4.4.5 The CONSTANT_Long_info and CONSTANT_Double_info Structures + * Models a {@code CONSTANT_Double_info} structure, representing a {@code + * double} constant, in the constant pool of a {@code class} file. + *

    + * The use of a {@code DoubleEntry} is modeled by a {@code double}. Conversions + * are through {@link ConstantPoolBuilder#doubleEntry} and {@link #doubleValue()}. + * In the conversions, all NaN values of the {@code double} may be collapsed + * into a single {@linkplain Double#NaN "canonical" NaN value}. + *

    + * A double entry has a {@linkplain #width() width} of {@code 2}, making its + * subsequent constant pool index valid and unusable. * + * @see ConstantPoolBuilder#doubleEntry ConstantPoolBuilder::doubleEntry + * @jvms 4.4.5 The {@code CONSTANT_Long_info} and {@code CONSTANT_Double_info} + * Structures * @since 24 */ public sealed interface DoubleEntry @@ -40,13 +50,13 @@ public sealed interface DoubleEntry permits AbstractPoolEntry.DoubleEntryImpl { /** - * {@return the double value} + * {@return the {@code double} value} + * + * @see ConstantPoolBuilder#doubleEntry(double) + * ConstantPoolBuilder::doubleEntry(double) */ double doubleValue(); - /** - * {@return the type of the constant} - */ @Override default TypeKind typeKind() { return TypeKind.DOUBLE; diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/DynamicConstantPoolEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/DynamicConstantPoolEntry.java index 3ec4fbbdbee..b72424db44e 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/DynamicConstantPoolEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/DynamicConstantPoolEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,10 +27,27 @@ import java.lang.classfile.BootstrapMethodEntry; /** - * Models a dynamic constant pool entry, which is either {@link ConstantDynamicEntry} - * or {@link InvokeDynamicEntry}. - * @jvms 4.4.10 The CONSTANT_Dynamic_info and CONSTANT_InvokeDynamic_info Structures + * Superinterface modeling dynamically-computed constant pool entries, which + * include {@link ConstantDynamicEntry} and {@link InvokeDynamicEntry}, in the + * constant pool of a {@code class} file. + *

    + * Different types of dynamically-computed constant pool entries bear structural + * similarities, but they appear in distinct locations. As a result, their uses + * are represented by different symbolic descriptors, specific to each subtype. + *

    + * A dynamic constant entry is composite: + * {@snippet lang=text : + * DynamicConstantPoolEntry( + * BootstrapMethodEntry bootstrap, // @link substring="bootstrap" target="#bootstrap()" + * NameAndTypeEntry nameAndType // @link substring="nameAndType" target="#nameAndType()" + * ) + * } * + * @see java.lang.invoke##jvm_mods Dynamic resolution of call sites and + * constants + * @jvms 4.4.10 The {@code CONSTANT_Dynamic_info} and {@code + * CONSTANT_InvokeDynamic_info} Structures + * @jvms 5.4.3.6 Dynamically-Computed Constant and Call Site Resolution * @sealedGraph * @since 24 */ @@ -39,28 +56,50 @@ public sealed interface DynamicConstantPoolEntry extends PoolEntry /** * {@return the entry in the bootstrap method table for this constant} + * + * @see java.lang.invoke##bsm Execution of bootstrap methods + * @see ConstantPoolBuilder#constantDynamicEntry(BootstrapMethodEntry, NameAndTypeEntry) + * ConstantPoolBuilder::constantDynamicEntry(BootstrapMethodEntry, NameAndTypeEntry) + * @see ConstantPoolBuilder#invokeDynamicEntry(BootstrapMethodEntry, NameAndTypeEntry) + * ConstantPoolBuilder::invokeDynamicEntry(BootstrapMethodEntry, NameAndTypeEntry) */ BootstrapMethodEntry bootstrap(); /** - * {@return index of the entry in the bootstrap method table for this constant} + * {@return index of the entry in the bootstrap method table for this + * constant} The return value is equivalent to {@code + * bootstrap().bsmIndex()}. */ int bootstrapMethodIndex(); /** - * {@return the invocation name and type} + * {@return the name and the descriptor string indicated by this symbolic + * reference} + * + * @see java.lang.invoke##bsm Execution of bootstrap methods + * @see ConstantPoolBuilder#constantDynamicEntry(BootstrapMethodEntry, NameAndTypeEntry) + * ConstantPoolBuilder::constantDynamicEntry(BootstrapMethodEntry, NameAndTypeEntry) + * @see ConstantPoolBuilder#invokeDynamicEntry(BootstrapMethodEntry, NameAndTypeEntry) + * ConstantPoolBuilder::invokeDynamicEntry(BootstrapMethodEntry, NameAndTypeEntry) */ NameAndTypeEntry nameAndType(); /** - * {@return the invocation name} + * {@return the name indicated by this symbolic reference} */ default Utf8Entry name() { return nameAndType().name(); } /** - * {@return the invocation type} + * {@return the descriptor string indicated by this symbolic reference} + * This is a field descriptor string if this entry is a {@link + * ConstantDynamicEntry}, or a method descriptor string if this entry is a + * {@link InvokeDynamicEntry}. + * + * @apiNote + * Each subinterface has its specific accessor named {@code typeSymbol} for + * the symbolic descriptor derived from this descriptor string. */ default Utf8Entry type() { return nameAndType().type(); diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/FieldRefEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/FieldRefEntry.java index 47f5b6710d8..9f984acd7ba 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/FieldRefEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/FieldRefEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,17 +30,31 @@ import jdk.internal.classfile.impl.Util; /** - * Models a {@code CONSTANT_Fieldref_info} constant in the constant pool of a - * classfile. - * @jvms 4.4.2 The CONSTANT_Fieldref_info, CONSTANT_Methodref_info, and CONSTANT_InterfaceMethodref_info Structures + * Models a {@code CONSTANT_Fieldref_info} structure, or a symbolic reference + * to a field, in the constant pool of a {@code class} file. + *

    + * A field reference constant pool entry is composite: + * {@snippet lang=text : + * // @link substring="FieldRefEntry" target="ConstantPoolBuilder#fieldRefEntry(ClassEntry, NameAndTypeEntry)" : + * FieldRefEntry( + * ClassEntry owner, // @link substring="owner" target="#owner()" + * NameAndTypeEntry nameAndType // @link substring="nameAndType" target="#nameAndType()" + * ) + * } + * where the {@link #type() nameAndType.type()} represents a {@linkplain + * #typeSymbol() field descriptor} string. * + * @see ConstantPoolBuilder#fieldRefEntry ConstantPoolBuilder::fieldRefEntry + * @jvms 4.4.2 The {@code CONSTANT_Fieldref_info}, {@code + * CONSTANT_Methodref_info}, and {@code + * CONSTANT_InterfaceMethodref_info} Structures * @since 24 */ public sealed interface FieldRefEntry extends MemberRefEntry permits AbstractPoolEntry.FieldRefEntryImpl { /** - * {@return a symbolic descriptor for the field's type} + * {@return a symbolic descriptor for the {@linkplain #type() field type}} */ default ClassDesc typeSymbol() { return Util.fieldTypeSymbol(type()); diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/FloatEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/FloatEntry.java index eeb44e92b7c..2ccf3fb94e4 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/FloatEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/FloatEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,10 +29,17 @@ import jdk.internal.classfile.impl.AbstractPoolEntry; /** - * Models a {@code CONSTANT_Float_info} constant in the constant pool of a - * classfile. - * @jvms 4.4.4 The CONSTANT_Integer_info and CONSTANT_Float_info Structures + * Models a {@code CONSTANT_Float_info} structure, or a {@code float} constant, + * in the constant pool of a {@code class} file. + *

    + * The use of a {@code FloatEntry} is modeled by a {@code float}. Conversions + * are through {@link ConstantPoolBuilder#floatEntry} and {@link #floatValue()}. + * In the conversions, all NaN values of the {@code float} may be collapsed into + * a single {@linkplain Float#NaN "canonical" NaN value}. * + * @see ConstantPoolBuilder#floatEntry ConstantPoolBuilder::floatEntry + * @jvms 4.4.4 The {@code CONSTANT_Integer_info} and {@code CONSTANT_Float_info} + * Structures * @since 24 */ public sealed interface FloatEntry @@ -40,14 +47,12 @@ public sealed interface FloatEntry permits AbstractPoolEntry.FloatEntryImpl { /** - * {@return the float value} + * {@return the {@code float} value} + * + * @see ConstantPoolBuilder#floatEntry(float) */ - float floatValue(); - /** - * {@return the type of the constant} - */ @Override default TypeKind typeKind() { return TypeKind.FLOAT; diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/IntegerEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/IntegerEntry.java index 908f17d1cb7..d6d2c28ed57 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/IntegerEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/IntegerEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,10 +29,15 @@ import jdk.internal.classfile.impl.AbstractPoolEntry; /** - * Models a {@code CONSTANT_Integer_info} constant in the constant pool of a - * classfile. - * @jvms 4.4.4 The CONSTANT_Integer_info and CONSTANT_Float_info Structures + * Models a {@code CONSTANT_Integer_info} structure, or an {@code int} constant, + * in the constant pool of a {@code class} file. + *

    + * The use of a {@code IntegerEntry} is modeled by an {@code int}. Conversions + * are through {@link ConstantPoolBuilder#intEntry(int)} and {@link #intValue()}. * + * @see ConstantPoolBuilder#intEntry ConstantPoolBuilder::intEntry + * @jvms 4.4.4 The {@code CONSTANT_Integer_info} and {@code CONSTANT_Float_info} + * Structures * @since 24 */ public sealed interface IntegerEntry @@ -40,13 +45,12 @@ public sealed interface IntegerEntry permits AbstractPoolEntry.IntegerEntryImpl { /** - * {@return the integer value} + * {@return the {@code int} value} + * + * @see ConstantPoolBuilder#intEntry(int) */ int intValue(); - /** - * {@return the type of the constant} - */ @Override default TypeKind typeKind() { return TypeKind.INT; diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/InterfaceMethodRefEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/InterfaceMethodRefEntry.java index 7b1a94f123a..e29c9f5b6f9 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/InterfaceMethodRefEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/InterfaceMethodRefEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,10 +30,26 @@ import jdk.internal.classfile.impl.Util; /** - * Models a {@code CONSTANT_InterfaceMethodRef_info} constant in the constant pool of a - * classfile. - * @jvms 4.4.2 The CONSTANT_Fieldref_info, CONSTANT_Methodref_info, and CONSTANT_InterfaceMethodref_info Structures + * Models a {@code CONSTANT_InterfaceMethodRef_info} structure, or a symbolic + * reference to an interface method, in the constant pool of a {@code class} + * file. + *

    + * An interface method reference entry is composite: + * {@snippet lang=text : + * // @link substring="InterfaceMethodRefEntry" target="ConstantPoolBuilder#interfaceMethodRefEntry(ClassEntry, NameAndTypeEntry)" : + * InterfaceMethodRefEntry( + * ClassEntry owner, // @link substring="owner" target="#owner()" + * NameAndTypeEntry nameAndType // @link substring="nameAndType" target="#nameAndType()" + * ) + * } + * where the {@link #type() type} in the {@code nameAndType} is a {@linkplain + * #typeSymbol() method descriptor} string. * + * @see ConstantPoolBuilder#interfaceMethodRefEntry + * ConstantPoolBuilder::interfaceMethodRefEntry + * @jvms 4.4.2 The {@code CONSTANT_Fieldref_info}, {@code + * CONSTANT_Methodref_info}, and {@code + * CONSTANT_InterfaceMethodref_info} Structures * @since 24 */ public sealed interface InterfaceMethodRefEntry @@ -41,7 +57,7 @@ public sealed interface InterfaceMethodRefEntry permits AbstractPoolEntry.InterfaceMethodRefEntryImpl { /** - * {@return a symbolic descriptor for the interface method's type} + * {@return a symbolic descriptor for the {@linkplain #type() method type}} */ default MethodTypeDesc typeSymbol() { return Util.methodTypeSymbol(type()); diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/InvokeDynamicEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/InvokeDynamicEntry.java index 0cc8b6823df..02c2fce2e02 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/InvokeDynamicEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/InvokeDynamicEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,9 +32,38 @@ import jdk.internal.classfile.impl.Util; /** - * Models a constant pool entry for a dynamic call site. - * @jvms 4.4.10 The CONSTANT_Dynamic_info and CONSTANT_InvokeDynamic_info Structures + * Models a {@code CONSTANT_InvokeDynamic_info} structure, or the symbolic + * reference to a {@index "dynamically-computed call site"}, in the + * constant pool of a {@code class} file. + *

    + * The use of a {@code InvokeDynamicEntry} is modeled by a {@link + * DynamicCallSiteDesc} symbolic descriptor. It can be obtained from {@link + * #asSymbol() InvokeDynamicEntry::asSymbol} and converted back to a constant + * pool entry through {@link ConstantPoolBuilder#invokeDynamicEntry(DynamicCallSiteDesc) + * ConstantPoolBuilder::invokeDynamicEntry}. + *

    + * An invoke dynamic entry is composite: + * {@snippet lang=text : + * // @link substring="InvokeDynamicEntry" target="ConstantPoolBuilder#invokeDynamicEntry(BootstrapMethodEntry, NameAndTypeEntry)" : + * InvokeDynamicEntry( + * BootstrapMethodEntry bootstrap, // @link substring="bootstrap" target="#bootstrap()" + * NameAndTypeEntry nameAndType // @link substring="nameAndType" target="#nameAndType()" + * ) + * } + * where the {@link #type() type} in the {@code nameAndType} is a {@linkplain + * #typeSymbol() method descriptor} string. * + * @apiNote + * A dynamically-computed call site is frequently called a {@index "dynamic + * call site"}, or an {@index "indy"}, from the abbreviation of + * "invoke dynamic". + * + * @see ConstantPoolBuilder#invokeDynamicEntry + * ConstantPoolBuilder::invokeDynamicEntry + * @see DynamicCallSiteDesc + * @see java.lang.invoke##indyinsn Dynamically-computed call sites + * @jvms 4.4.10 The {@code CONSTANT_Dynamic_info} and {@code + * CONSTANT_InvokeDynamic_info} Structures * @since 24 */ public sealed interface InvokeDynamicEntry @@ -42,14 +71,18 @@ public sealed interface InvokeDynamicEntry permits AbstractPoolEntry.InvokeDynamicEntryImpl { /** - * {@return a symbolic descriptor for the call site's invocation type} + * {@return a symbolic descriptor for the {@linkplain #type() invocation + * type} of this dynamic call site} */ default MethodTypeDesc typeSymbol() { return Util.methodTypeSymbol(type()); } /** - * {@return a symbolic descriptor for the dynamic call site} + * {@return a symbolic descriptor for this dynamic call site} + * + * @see ConstantPoolBuilder#invokeDynamicEntry(DynamicCallSiteDesc) + * ConstantPoolBuilder::invokeDynamicEntry(DynamicCallSiteDesc) */ default DynamicCallSiteDesc asSymbol() { return DynamicCallSiteDesc.of(bootstrap().bootstrapMethod().asSymbol(), diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/LoadableConstantEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/LoadableConstantEntry.java index 32f85f64c7e..9137bebea35 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/LoadableConstantEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/LoadableConstantEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,13 +24,22 @@ */ package java.lang.classfile.constantpool; +import java.lang.classfile.CodeBuilder; +import java.lang.classfile.Opcode; import java.lang.classfile.TypeKind; +import java.lang.classfile.instruction.ConstantInstruction; import java.lang.constant.ConstantDesc; /** * Marker interface for constant pool entries suitable for loading via the - * {@code LDC} instructions. + * {@link ConstantInstruction.LoadConstantInstruction ldc} instructions. + *

    + * The use of a {@code LoadableConstantEntry} is modeled by a {@link ConstantDesc}. + * Conversions are through {@link ConstantPoolBuilder#loadableConstantEntry(ConstantDesc)} + * and {@link #constantValue()}. * + * @see CodeBuilder#ldc(LoadableConstantEntry) + * @jvms 4.4 The Constant Pool * @sealedGraph * @since 24 */ @@ -38,12 +47,19 @@ public sealed interface LoadableConstantEntry extends PoolEntry permits ClassEntry, ConstantDynamicEntry, ConstantValueEntry, MethodHandleEntry, MethodTypeEntry { /** - * {@return the constant described by this entry} + * {@return a symbolic descriptor of this constant} + * + * @see ConstantPoolBuilder#loadableConstantEntry(ConstantDesc) */ ConstantDesc constantValue(); /** - * {@return the type of the constant} + * {@return the data type of this constant} + *

    + * If the data type is of {@linkplain TypeKind#slotSize() category} 2, this + * constant must be loaded with {@link Opcode#LDC2_W ldc2_w}; otherwise, the + * data type is of category 1, and this constant must be loaded with {@link + * Opcode#LDC ldc} or {@link Opcode#LDC_W ldc_w}. */ default TypeKind typeKind() { return TypeKind.REFERENCE; diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/LongEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/LongEntry.java index cd38dcfe014..dbf947d1f1d 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/LongEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/LongEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,10 +29,18 @@ import jdk.internal.classfile.impl.AbstractPoolEntry; /** - * Models a {@code CONSTANT_Long_info} constant in the constant pool of a - * classfile. - * @jvms 4.4.5 The CONSTANT_Long_info and CONSTANT_Double_info Structures + * Models a {@code CONSTANT_Long_info} structure, or a {@code long} constant, in + * the constant pool of a {@code class} file. + *

    + * The use of a {@code LongEntry} is modeled by a {@code long}. Conversions are + * through {@link ConstantPoolBuilder#longEntry(long)} and {@link #longValue()}. + *

    + * A long entry has a {@linkplain #width() width} of {@code 2}, making its + * subsequent constant pool index valid and unusable. * + * @see ConstantPoolBuilder#longEntry ConstantPoolBuilder::longEntry + * @jvms 4.4.5 The {@code CONSTANT_Long_info} and {@code CONSTANT_Double_info} + * Structures * @since 24 */ public sealed interface LongEntry @@ -40,7 +48,10 @@ public sealed interface LongEntry permits AbstractPoolEntry.LongEntryImpl { /** - * {@return the long value} + * {@return the {@code long} value} + * + * @see ConstantPoolBuilder#longEntry(long) + * ConstantPoolBuilder::longEntry(long) */ long longValue(); diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/MemberRefEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/MemberRefEntry.java index 12d68796dd7..3d59a3c96c9 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/MemberRefEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/MemberRefEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,24 +24,45 @@ */ package java.lang.classfile.constantpool; +import java.lang.classfile.Opcode; + import jdk.internal.classfile.impl.AbstractPoolEntry; /** - * Models a member reference constant in the constant pool of a classfile, - * which includes references to fields, methods, and interface methods. + * Superinterface modeling symbolic references to a member of a class or interface + * in the constant pool of a {@code class} file, which include references to + * {@linkplain FieldRefEntry fields}, {@linkplain MethodRefEntry class methods}, + * and {@linkplain InterfaceMethodRefEntry interface methods}. + *

    + * Different types of symbolic references to a member of a class or interface + * bear structural similarities and share parts of the resolution processes, and + * they can sometimes appear in the same locations. For example, both {@link + * MethodRefEntry} and {@link InterfaceMethodRefEntry} can appear in an {@link + * Opcode#INVOKESTATIC invokestatic} instruction. + *

    + * A member reference entry is composite: + * {@snippet lang=text : + * MemberRefEntry( + * ClassEntry owner, // @link substring="owner" target="#owner()" + * NameAndTypeEntry nameAndType // @link substring="nameAndType" target="#nameAndType()" + * ) + * } * + * @jvms 4.4.2 The {@code CONSTANT_Fieldref_info}, {@code + * CONSTANT_Methodref_info}, and {@code + * CONSTANT_InterfaceMethodref_info} Structures * @sealedGraph * @since 24 */ public sealed interface MemberRefEntry extends PoolEntry permits FieldRefEntry, InterfaceMethodRefEntry, MethodRefEntry, AbstractPoolEntry.AbstractMemberRefEntry { /** - * {@return the class in which this member ref lives} + * {@return the class or interface which this member belongs to} */ ClassEntry owner(); /** - * {@return the name and type of the member} + * {@return the name and descriptor string of the member} */ NameAndTypeEntry nameAndType(); @@ -53,7 +74,14 @@ default Utf8Entry name() { } /** - * {@return the type of the member} + * {@return the descriptor string of the member} This is a field descriptor + * string if this entry is a {@link FieldRefEntry}, or a method descriptor + * string if this entry is a {@link MethodRefEntry} or {@link + * InterfaceMethodRefEntry}. + * + * @apiNote + * Each subinterface defines a {@code typeSymbol()} accessor for the + * symbolic descriptor for the member type. */ default Utf8Entry type() { return nameAndType().type(); diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/MethodHandleEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/MethodHandleEntry.java index d2e08ef178c..22c07236e8a 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/MethodHandleEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/MethodHandleEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,13 +26,35 @@ import java.lang.constant.ConstantDesc; import java.lang.constant.DirectMethodHandleDesc; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandleInfo; import jdk.internal.classfile.impl.AbstractPoolEntry; /** - * Models a {@code CONSTANT_MethodHandle_info} constant in the constant pool of a - * classfile. - * @jvms 4.4.8 The CONSTANT_MethodHandle_info Structure + * Models a {@code CONSTANT_MethodHandle_info} structure, or a symbolic + * reference to a {@linkplain MethodHandle method handle}, in the constant pool + * of a {@code class} file. The method handle directly accesses an accessible + * method, field, or constructor. + *

    + * The use of a {@code MethodHandleEntry} is modeled by a {@link + * DirectMethodHandleDesc}. Conversions are through {@link + * ConstantPoolBuilder#methodHandleEntry(DirectMethodHandleDesc)} and {@link + * #asSymbol()}. + *

    + * A method handle entry is composite: + * {@snippet lang=text : + * // @link substring="MethodHandleEntry" target="ConstantPoolBuilder#methodHandleEntry(int, MemberRefEntry)" : + * MethodHandleEntry( + * int refKind, // @link substring="refKind" target="#kind()" + * MemberRefEntry reference // @link substring="reference" target="#reference()" + * ) + * } + * where {@code refKind} is in the range {@code [1, 9]}. + * + * @see ConstantPoolBuilder#methodHandleEntry + * ConstantPoolBuilder::methodHandleEntry + * @jvms 4.4.8 The {@code CONSTANT_MethodHandle_info} Structure * * @since 24 */ @@ -40,6 +62,11 @@ public sealed interface MethodHandleEntry extends LoadableConstantEntry permits AbstractPoolEntry.MethodHandleEntryImpl { + /** + * {@inheritDoc} + *

    + * This is equivalent to {@link #asSymbol() asSymbol()}. + */ @Override default ConstantDesc constantValue() { return asSymbol(); @@ -47,17 +74,22 @@ default ConstantDesc constantValue() { /** * {@return the reference kind of this method handle (JVMS {@jvms 4.4.8})} - * @see java.lang.invoke.MethodHandleInfo + * + * @see MethodHandleInfo##refkinds Reference kinds */ int kind(); /** - * {@return the constant pool entry describing the method} + * {@return the constant pool entry describing the field or method, + * according to the {@linkplain #kind() reference kind}} */ MemberRefEntry reference(); /** * {@return a symbolic descriptor for this method handle} + * + * @see ConstantPoolBuilder#methodHandleEntry(DirectMethodHandleDesc) + * ConstantPoolBuilder::methodHandleEntry(DirectMethodHandleDesc) */ DirectMethodHandleDesc asSymbol(); } diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/MethodRefEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/MethodRefEntry.java index 5be9e88fa2f..29503741ec3 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/MethodRefEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/MethodRefEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,17 +30,31 @@ import jdk.internal.classfile.impl.Util; /** - * Models a {@code CONSTANT_MethodRef_info} constant in the constant pool of a - * classfile. - * @jvms 4.4.2 The CONSTANT_Fieldref_info, CONSTANT_Methodref_info, and CONSTANT_InterfaceMethodref_info Structures + * Models a {@code CONSTANT_MethodRef_info} structure, or a symbolic reference + * to a class method, in the constant pool of a {@code class} file. + *

    + * A class method reference entry is composite: + * {@snippet lang=text : + * // @link substring="MethodRefEntry" target="ConstantPoolBuilder#methodRefEntry(ClassEntry, NameAndTypeEntry)" : + * MethodRefEntry( + * ClassEntry owner, // @link substring="owner" target="#owner()" + * NameAndTypeEntry nameAndType // @link substring="nameAndType" target="#nameAndType()" + * ) + * } + * where the type in the {@code NameAndTypeEntry} is a {@linkplain #typeSymbol() + * method descriptor} string. * + * @see ConstantPoolBuilder#methodRefEntry ConstantPoolBuilder::methodRefEntry + * @jvms 4.4.2 The {@code CONSTANT_Fieldref_info}, {@code + * CONSTANT_Methodref_info}, and {@code + * CONSTANT_InterfaceMethodref_info} Structures * @since 24 */ public sealed interface MethodRefEntry extends MemberRefEntry permits AbstractPoolEntry.MethodRefEntryImpl { /** - * {@return a symbolic descriptor for the method's type} + * {@return a symbolic descriptor for the {@linkplain #type() method type}} */ default MethodTypeDesc typeSymbol() { return Util.methodTypeSymbol(type()); diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/MethodTypeEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/MethodTypeEntry.java index b6fad856358..5da36502678 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/MethodTypeEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/MethodTypeEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,28 +30,46 @@ import jdk.internal.classfile.impl.AbstractPoolEntry; /** - * Models a {@code CONSTANT_MethodType_info} constant in the constant pool of a - * classfile. - * @jvms 4.4.9 The CONSTANT_MethodType_info Structure + * Models a {@code CONSTANT_MethodType_info} structure, or a symbolic reference + * to a method type, in the constant pool of a {@code class} file. + *

    + * The use of a {@code MethodTypeEntry} is modeled by a {@link MethodTypeDesc}. + * Conversions are through {@link ConstantPoolBuilder#methodTypeEntry(MethodTypeDesc)} + * and {@link #asSymbol()}. + *

    + * A method type entry is composite: + * {@snippet lang=text : + * // @link substring="MethodTypeEntry" target="ConstantPoolBuilder#methodTypeEntry(Utf8Entry)" : + * MethodTypeEntry(Utf8Entry descriptor) // @link substring="descriptor" target="#descriptor()" + * } + * where {@code descriptor} is a {@linkplain #asSymbol() method descriptor} + * string. * + * @jvms 4.4.9 The {@code CONSTANT_MethodType_info} Structure * @since 24 */ public sealed interface MethodTypeEntry extends LoadableConstantEntry permits AbstractPoolEntry.MethodTypeEntryImpl { + /** + * {@inheritDoc} + *

    + * This is equivalent to {@link #asSymbol() asSymbol()}. + */ @Override default ConstantDesc constantValue() { return asSymbol(); } /** - * {@return the constant pool entry describing the method type} + * {@return the {@linkplain #asSymbol() method descriptor} string} */ Utf8Entry descriptor(); /** - * {@return a symbolic descriptor for the method type} + * {@return a symbolic descriptor for the {@linkplain #descriptor() method + * type}} */ MethodTypeDesc asSymbol(); } diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/ModuleEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/ModuleEntry.java index d0cdae5678f..fd920aa1231 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/ModuleEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/ModuleEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,21 +29,32 @@ import jdk.internal.classfile.impl.AbstractPoolEntry; /** - * Models a {@code CONSTANT_Module_info} constant in the constant pool of a - * classfile. - * @jvms 4.4.11 The CONSTANT_Module_info Structure + * Models a {@code CONSTANT_Module_info} structure, denoting a module, in the + * constant pool of a {@code class} file. + *

    + * The use of a {@code ModuleEntry} is modeled by a {@link ModuleDesc}. + * Conversions are through {@link ConstantPoolBuilder#moduleEntry(ModuleDesc)} + * and {@link #asSymbol()}. + *

    + * A module entry is composite: + * {@snippet lang=text : + * // @link substring="ModuleEntry" target="ConstantPoolBuilder#moduleEntry(Utf8Entry)" : + * ModuleEntry(Utf8Entry name) // @link substring="name" target="#name()" + * } + * where {@code name} is a {@linkplain #asSymbol() module name}. * + * @jvms 4.4.11 The {@code CONSTANT_Module_info} Structure * @since 24 */ public sealed interface ModuleEntry extends PoolEntry permits AbstractPoolEntry.ModuleEntryImpl { /** - * {@return the name of the module} + * {@return the name of the {@linkplain #asSymbol() module}} */ Utf8Entry name(); /** - * {@return a symbolic descriptor for the module} + * {@return a symbolic descriptor for the {@linkplain #name() module name}} */ ModuleDesc asSymbol(); } diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/NameAndTypeEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/NameAndTypeEntry.java index eff7e3456d1..38a23b0940e 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/NameAndTypeEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/NameAndTypeEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,13 +24,36 @@ */ package java.lang.classfile.constantpool; +import java.lang.constant.ClassDesc; +import java.lang.constant.MethodTypeDesc; +import java.lang.invoke.TypeDescriptor; + import jdk.internal.classfile.impl.AbstractPoolEntry; /** - * Models a {@code CONSTANT_NameAndType_info} constant in the constant pool of a - * classfile. - * @jvms 4.4.6 The CONSTANT_NameAndType_info Structure + * Models a {@code CONSTANT_NameAndType_info} structure, representing a field or + * method, in the constant pool of a {@code class} file. + *

    + * The use of a {@code NameAndTypeEntry} is symbolically represented as a + * {@code String name}, and a {@link ConstantPoolBuilder#nameAndTypeEntry(String, + * ClassDesc) ClassDesc} or a {@link ConstantPoolBuilder#nameAndTypeEntry(String, + * MethodTypeDesc) MethodTypeDesc} {@code type}, depending on where this {@code + * NameAndTypeEntry} appears. The accessors to the symbolic descriptors for the + * {@code type} is defined on a per-use-site basis, such as {@link + * FieldRefEntry#typeSymbol()} returning a {@code ClassDesc}, and {@link + * MethodRefEntry#typeSymbol()} returning a {@code MethodTypeDesc}. + *

    + * A name and type entry is composite: + * {@snippet lang=text : + * NameAndTypeEntry( // @link substring="NameAndTypeEntry" target="ConstantPoolBuilder#nameAndTypeEntry(Utf8Entry, Utf8Entry)" + * Utf8Entry name, // @link substring="name" target="#name()" + * Utf8Entry type // @link substring="type" target="#type()" + * ) + * } + * where {@code name} is an unqualified name, and {@code type} is a field or + * method descriptor string. * + * @jvms 4.4.6 The {@code CONSTANT_NameAndType_info} Structure * @since 24 */ public sealed interface NameAndTypeEntry extends PoolEntry @@ -42,7 +65,10 @@ public sealed interface NameAndTypeEntry extends PoolEntry Utf8Entry name(); /** - * {@return the field or method descriptor} + * {@return the field or method {@linkplain TypeDescriptor descriptor} + * string} It is a method descriptor strings if it starts with {@code (}. + * Otherwise, it is a field descriptor string, and must start with one of + * the {@code BCDFIJSZL[} characters. */ Utf8Entry type(); } diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/PackageEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/PackageEntry.java index 54ea2fc38e5..ec56d0a4870 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/PackageEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/PackageEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,21 +29,35 @@ import jdk.internal.classfile.impl.AbstractPoolEntry; /** - * Models a {@code CONSTANT_Package_info} constant in the constant pool of a - * classfile. - * @jvms 4.4.12 The CONSTANT_Package_info Structure + * Models a {@code CONSTANT_Package_info}, representing a package, in the + * constant pool of a {@code class} file. + *

    + * The use of a {@code PackageEntry} is represented by a {@link PackageDesc} + * that does not represent the unnamed package. Conversions are through + * {@link ConstantPoolBuilder#packageEntry(PackageDesc)} and + * {@link #asSymbol()}. + *

    + * A package entry is composite: + * {@snippet lang=text : + * // @link substring="PackageEntry" target="ConstantPoolBuilder#packageEntry(Utf8Entry)" : + * PackageEntry(Utf8Entry name) // @link substring="name" target="#name()" + * } + * where {@code name} is the {@linkplain ClassEntry##internalname internal form} + * of a binary package name and is not empty. * + * @jvms 4.4.12 The {@code CONSTANT_Package_info} Structure * @since 24 */ public sealed interface PackageEntry extends PoolEntry permits AbstractPoolEntry.PackageEntryImpl { /** - * {@return the package name} + * {@return the {@linkplain ClassEntry##internalname internal form} of the + * {@linkplain #asSymbol() package} name} */ Utf8Entry name(); /** - * {@return a symbolic descriptor for the package name} + * {@return a symbolic descriptor for the {@linkplain #name() package name}} */ PackageDesc asSymbol(); } diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/PoolEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/PoolEntry.java index 5762a92a061..5d27e54e679 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/PoolEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/PoolEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,9 +24,28 @@ */ package java.lang.classfile.constantpool; +import java.lang.classfile.Attribute; +import java.lang.classfile.ClassFileBuilder; +import java.lang.classfile.Opcode; +import java.lang.classfile.TypeKind; + /** - * Models an entry in the constant pool of a classfile. + * Models an entry in the constant pool of a {@code class} file. Entries are + * read from {@code class} files, and can be created with a {@link + * ConstantPoolBuilder} to write to {@code class} files. + * + * @implNote + *

    Unbound Constant Pool Entries

    + * Implementations may create unbound constant pool entries not belonging to + * an actual constant pool. They conveniently represent constant pool entries + * referred by unbound {@linkplain Attribute attributes} not read from a {@code + * class} file. Their {@link #index() index()} return a non-positive invalid + * value, and behaviors of their {@link #constantPool() constantPool()} are + * unspecified. They are considered alien to any {@linkplain + * ClassFileBuilder#constantPool() contextual constant pool} and will be + * converted when they are written to {@code class} files. * + * @see ConstantPoolBuilder##alien Alien Constant Pool Entries * @sealedGraph * @since 24 */ @@ -88,6 +107,14 @@ public sealed interface PoolEntry /** * {@return the constant pool this entry is from} + * + * @apiNote + * Given a {@link ConstantPoolBuilder} {@code builder} and a {@code + * PoolEntry entry}, use {@link ConstantPoolBuilder#canWriteDirect + * builder.canWriteDirect(entry.constantPool())} instead of object equality + * of the constant pool to determine if an entry belongs to the builder. + * + * @see ##unbound Unbound Constant Pool Entries */ ConstantPool constantPool(); @@ -102,11 +129,32 @@ public sealed interface PoolEntry /** * {@return the index within the constant pool corresponding to this entry} + * A valid index is always positive; if the index is non-positive, this + * entry is {@linkplain ##unbound unbound}. + * + * @see ##unbound Unbound Constant Pool Entries */ int index(); /** * {@return the number of constant pool slots this entry consumes} + *

    + * All pool entries except {@link LongEntry CONSTANT_Long} and {@link + * DoubleEntry CONSTANT_Double} have width {@code 1}. These two exceptions + * have width {@code 2}, and their subsequent indices at {@link #index() + * index() + 1} are considered unusable. + * + * @apiNote + * If this entry is {@linkplain LoadableConstantEntry loadable}, the width + * of this entry does not decide if this entry should be loaded with {@link + * Opcode#LDC ldc} or {@link Opcode#LDC2_W ldc2_w}. For example, {@link + * ConstantDynamicEntry} always has width {@code 1}, but it must be loaded + * with {@code ldc2_w} if its {@linkplain ConstantDynamicEntry#typeKind() + * type} is {@link TypeKind#LONG long} or {@link TypeKind#DOUBLE double}. + * Use {@link LoadableConstantEntry#typeKind() typeKind().slotSize()} to + * determine the loading instruction instead. + * + * @see ConstantPool##index Index in the Constant Pool */ int width(); } diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/StringEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/StringEntry.java index 03ff7652f67..8a0bbb4b015 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/StringEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/StringEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,10 +27,20 @@ import jdk.internal.classfile.impl.AbstractPoolEntry; /** - * Models a {@code CONSTANT_String_info} constant in the constant pool of a - * classfile. - * @jvms 4.4.3 The CONSTANT_String_info Structure + * Models a {@code CONSTANT_String_info} structure, or a string constant, in the + * constant pool of a {@code class} file. + *

    + * The use of a {@code StringEntry} is represented by a {@link String}. + * Conversions are through {@link ConstantPoolBuilder#stringEntry(String)} and + * {@link #stringValue()}. + *

    + * A string entry is composite: + * {@snippet lang=text : + * // @link substring="StringEntry" target="ConstantPoolBuilder#stringEntry(Utf8Entry)" : + * StringEntry(Utf8Entry utf8) // @link substring="utf8" target="#utf8()" + * } * + * @jvms 4.4.3 The {@code CONSTANT_String_info} Structure * @since 24 */ public sealed interface StringEntry @@ -38,11 +48,15 @@ public sealed interface StringEntry permits AbstractPoolEntry.StringEntryImpl { /** * {@return the UTF constant pool entry describing the string contents} + * + * @see ConstantPoolBuilder#stringEntry(Utf8Entry) */ Utf8Entry utf8(); /** * {@return the string value for this entry} + * + * @see ConstantPoolBuilder#stringEntry(String) */ String stringValue(); } diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/Utf8Entry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/Utf8Entry.java index db03bf6a403..1d885051b2b 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/Utf8Entry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/Utf8Entry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,13 +24,40 @@ */ package java.lang.classfile.constantpool; +import java.io.DataInput; +import java.lang.classfile.AnnotationValue; +import java.lang.classfile.MethodModel; +import java.lang.constant.ClassDesc; +import java.lang.constant.MethodTypeDesc; +import java.lang.invoke.TypeDescriptor; + import jdk.internal.classfile.impl.AbstractPoolEntry; /** - * Models a {@code CONSTANT_UTF8_info} constant in the constant pool of a - * classfile. - * @jvms 4.4.7 The CONSTANT_Utf8_info Structure + * Models a {@code CONSTANT_UTF8_info} constant, representing strings, in the + * constant pool of a {@code class} file. This describes strings in the + * {@linkplain DataInput##modified-utf-8 Modified UTF-8} format. + *

    + * The use of a {@code Utf8Entry} is represented by a {@link String}. + * Conversions are through {@link ConstantPoolBuilder#utf8Entry(String)} and + * {@link #stringValue()}. + *

    + * Some uses of {@code Utf8Entry} represent field or method {@linkplain + * TypeDescriptor#descriptorString() descriptor strings}, symbolically + * represented as {@link ClassDesc} or {@link MethodTypeDesc}, depending on + * where a {@code Utf8Entry} appear. Entries representing such uses are created + * with {@link ConstantPoolBuilder#utf8Entry(ClassDesc)} and {@link + * ConstantPoolBuilder#utf8Entry(MethodTypeDesc)}, and they can be converted to + * symbolic descriptors on a per-use-site basis, such as in {@link + * AnnotationValue.OfClass#classSymbol()} and {@link MethodModel#methodTypeSymbol()}. + *

    + * Unlike most constant pool entries, a UTF-8 entry is of flexible length: it is + * represented as an array structure, with an {@code u2} for the data length in + * bytes, followed by that number of bytes of Modified UTF-8 data. It can + * represent at most 65535 bytes of data due to the physical restrictions. * + * @jvms 4.4.7 The {@code CONSTANT_Utf8_info} Structure + * @see DataInput##modified-utf-8 Modified UTF-8 * @since 24 */ public sealed interface Utf8Entry @@ -39,6 +66,15 @@ public sealed interface Utf8Entry /** * {@return the string value for this entry} + * + * @apiNote + * A {@code Utf8Entry} can be used directly as a {@link CharSequence} if + * {@code String} functionalities are not strictly desired. If only string + * equivalence is desired, {@link #equalsString(String) equalsString} should + * be used. Reduction of string processing can significantly improve {@code + * class} file reading performance. + * + * @see ConstantPoolBuilder#utf8Entry(String) */ String stringValue(); diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/package-info.java b/src/java.base/share/classes/java/lang/classfile/constantpool/package-info.java index 83039c6565c..66e72496d3a 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/package-info.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,11 +24,59 @@ */ /** - *

    Provides interfaces describing classfile constant pool entries for the {@link java.lang.classfile} library.

    + *

    Provides interfaces describing constant pool entries for the {@link java.lang.classfile} library.

    * - * The {@code java.lang.classfile.constantpool} package contains interfaces describing classfile constant pool entries. + * The {@code java.lang.classfile.constantpool} package contains interfaces describing constant pool entries in the + * {@code class} file format. Constant pool entries are low-level models to faithfully represent the exact structure + * of a {@code class} file. + *

    + * Unless otherwise specified, passing {@code null} or an array or collection containing a {@code null} element as an + * argument to a constructor or method of any Class-File API class or interface will cause a {@link NullPointerException} + * to be thrown. * + *

    Reading the constant pool entries

    + * When read from {@code class} files, the pool entries are lazily inflated; the contents of these entries, besides the + * bare structure, are not evaluated to speed up parsing. Entries to users interest, usually accessed from other models + * and elements, have their contents read on demand. For example, to search for methods, a user should filter first by + * access flags and then by method name, and use {@link Utf8Entry#equalsString(String)} instead of checking equality + * against {@link Utf8Entry#stringValue()}. This avoids inflation of UTF-8 entries as much as possible: + * {@snippet lang="java" class="PackageSnippets" region="isStaticWorkMethod"} + *

    + * The entries also define accessors to validated symbolic information with nominal descriptor abstractions from the + * {@link java.lang.constant} package. These symbolic information accessors perform validation against the read + * {@code class} files, and throw {@link IllegalArgumentException} when the accessed constant pool entry contains + * invalid data. The nominal descriptors represent validated data, which saves users from extra validations in future + * processing. + *

    + * Due to the lazy nature of {@code class} file parsing, {@link IllegalArgumentException} indicating malformed + * {@code class} file data can be thrown at any method invocation. For example, an exception may come from a {@link + * ClassEntry} when it is first read from the constant pool (referring to an invalid index or wrong type of entry), when + * its referred UTF-8 entry is expanded (malformed UTF-8 data), or when its symbolic information is accessed (the string + * is not valid for a class entry). + * + *

    Writing the constant pool entries

    + * In general, users do not need to worry about working with the constant pool and its entries when writing {@code + * class} files. Most Class-File API models and elements have two sets of factory methods: one that accepts symbolic + * information representing the uses, and another that accepts constant pool entries. The constant pool builder + * associated with {@code class} file builders, {@link ClassFileBuilder#constantPool}, automatically creates or reuses + * pool entries from the symbolic information. Validated data in symbolic information helps {@code class} file + * generation by avoiding extraneous parsing of raw constant pool entry data. + *

    + * As always, users can use factories that accept constant pool entries if they already have them by hand, or if they + * desire fine-grained control over {@code class} file generation. + *

    + * If many models and elements are reused from another {@link ClassModel} in class building, the class building process + * can use a constant pool builder that extends from the given {@code ClassModel}, available through {@link + * ConstantPoolBuilder#of(ClassModel) ConstantPoolBuilder::of(ClassModel)}, so that byte data with constant pool + * references can be copied in batch, speeding up class building. This is especially applicable to class transformations, + * and {@link ClassFile.ConstantPoolSharingOption ConstantPoolSharingOption} exists to control this behavior. + * + * @jvms 4.4 The Constant Pool * @since 24 */ package java.lang.classfile.constantpool; +import java.lang.classfile.ClassFile; +import java.lang.classfile.ClassFileBuilder; +import java.lang.classfile.ClassModel; +import java.lang.classfile.MethodModel; diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/snippet-files/PackageSnippets.java b/src/java.base/share/classes/java/lang/classfile/constantpool/snippet-files/PackageSnippets.java new file mode 100644 index 00000000000..983aa1adb4c --- /dev/null +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/snippet-files/PackageSnippets.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package java.lang.classfile.constantpool.snippet; + +import java.lang.classfile.ClassFile; +import java.lang.classfile.MethodModel; +import java.lang.classfile.constantpool.Utf8Entry; + +class PackageSnippets { + + // @start region=isStaticWorkMethod + boolean isStaticWorkMethod(MethodModel method) { + // check static flag first to avoid unnecessary evaluation of UTF-8 entry + return (method.flags().flagsMask() & ClassFile.ACC_STATIC) != 0 + // use equalsString to avoid full conversion to String for comparison + // the Utf8Entry can also act as a basic CharSequence without full conversion + // @link substring="methodName" target="MethodModel#methodName" : + && method.methodName().equalsString("work"); // @link substring="equalsString" target="Utf8Entry#equalsString" + } + // @end +} diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/ArrayLoadInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/ArrayLoadInstruction.java index cc0e0b89f80..49bb708403e 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/ArrayLoadInstruction.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/ArrayLoadInstruction.java @@ -24,6 +24,7 @@ */ package java.lang.classfile.instruction; +import java.lang.classfile.CodeBuilder; import java.lang.classfile.CodeElement; import java.lang.classfile.CodeModel; import java.lang.classfile.Instruction; @@ -35,18 +36,29 @@ /** * Models an array load instruction in the {@code code} array of a {@code Code} - * attribute. Corresponding opcodes will have a {@code kind} of {@link - * Opcode.Kind#ARRAY_LOAD}. Delivered as a {@link CodeElement} when + * attribute. Corresponding opcodes have a {@linkplain Opcode#kind() kind} + * of {@link Opcode.Kind#ARRAY_LOAD}. Delivered as a {@link CodeElement} when * traversing the elements of a {@link CodeModel}. + *

    + * An array load instruction is composite: + * {@snippet lang=text : + * // @link substring="ArrayLoadInstruction" target="CodeBuilder#arrayLoad(TypeKind)" : + * ArrayLoadInstruction(TypeKind typeKind) // @link substring="typeKind" target="#typeKind" + * } + * where {@code typeKind} is not {@link TypeKind#VOID void}, and {@link + * TypeKind#BOOLEAN boolean} is converted to {@link TypeKind#BYTE byte}. * + * @see Opcode.Kind#ARRAY_LOAD + * @see CodeBuilder#arrayLoad CodeBuilder::arrayLoad * @since 24 */ public sealed interface ArrayLoadInstruction extends Instruction permits AbstractInstruction.UnboundArrayLoadInstruction { /** - * {@return the component type of the array} The {@link TypeKind#BYTE byte} + * {@return the component type of the array} The {@link TypeKind#BYTE byte} * type load instruction {@link Opcode#BALOAD baload} also operates on - * {@link TypeKind#BOOLEAN boolean} arrays. + * {@link TypeKind#BOOLEAN boolean} arrays, so this never returns + * {@code boolean}. */ TypeKind typeKind(); @@ -56,7 +68,7 @@ public sealed interface ArrayLoadInstruction extends Instruction * @param op the opcode for the specific type of array load instruction, * which must be of kind {@link Opcode.Kind#ARRAY_LOAD} * @throws IllegalArgumentException if the opcode kind is not - * {@link Opcode.Kind#ARRAY_LOAD}. + * {@link Opcode.Kind#ARRAY_LOAD} */ static ArrayLoadInstruction of(Opcode op) { Util.checkKind(op, Opcode.Kind.ARRAY_LOAD); diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/ArrayStoreInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/ArrayStoreInstruction.java index c350b3a5928..e5883a2cd2a 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/ArrayStoreInstruction.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/ArrayStoreInstruction.java @@ -24,6 +24,7 @@ */ package java.lang.classfile.instruction; +import java.lang.classfile.CodeBuilder; import java.lang.classfile.CodeElement; import java.lang.classfile.CodeModel; import java.lang.classfile.Instruction; @@ -35,18 +36,29 @@ /** * Models an array store instruction in the {@code code} array of a {@code Code} - * attribute. Corresponding opcodes will have a {@code kind} of {@link - * Opcode.Kind#ARRAY_STORE}. Delivered as a {@link CodeElement} when + * attribute. Corresponding opcodes have a {@linkplain Opcode#kind() kind} + * of {@link Opcode.Kind#ARRAY_STORE}. Delivered as a {@link CodeElement} when * traversing the elements of a {@link CodeModel}. + *

    + * An array store instruction is composite: + * {@snippet lang=text : + * // @link substring="ArrayStoreInstruction" target="CodeBuilder#arrayStore(TypeKind)" : + * ArrayStoreInstruction(TypeKind typeKind) // @link substring="typeKind" target="#typeKind" + * } + * where {@code typeKind} is not {@link TypeKind#VOID void}, and {@link + * TypeKind#BOOLEAN boolean} is converted to {@link TypeKind#BYTE byte}. * + * @see Opcode.Kind#ARRAY_STORE + * @see CodeBuilder#arrayStore CodeBuilder::arrayStore * @since 24 */ public sealed interface ArrayStoreInstruction extends Instruction permits AbstractInstruction.UnboundArrayStoreInstruction { /** - * {@return the component type of the array} The {@link TypeKind#BYTE byte} + * {@return the component type of the array} The {@link TypeKind#BYTE byte} * type store instruction {@link Opcode#BASTORE bastore} also operates on - * {@link TypeKind#BOOLEAN boolean} arrays. + * {@link TypeKind#BOOLEAN boolean} arrays, so this never returns + * {@code boolean}. */ TypeKind typeKind(); @@ -56,7 +68,7 @@ public sealed interface ArrayStoreInstruction extends Instruction * @param op the opcode for the specific type of array store instruction, * which must be of kind {@link Opcode.Kind#ARRAY_STORE} * @throws IllegalArgumentException if the opcode kind is not - * {@link Opcode.Kind#ARRAY_STORE}. + * {@link Opcode.Kind#ARRAY_STORE} */ static ArrayStoreInstruction of(Opcode op) { Util.checkKind(op, Opcode.Kind.ARRAY_STORE); diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/BranchInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/BranchInstruction.java index 2fdc00fced1..a37e37980d4 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/BranchInstruction.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/BranchInstruction.java @@ -24,28 +24,41 @@ */ package java.lang.classfile.instruction; -import java.lang.classfile.CodeElement; -import java.lang.classfile.CodeModel; -import java.lang.classfile.Instruction; -import java.lang.classfile.Label; -import java.lang.classfile.Opcode; +import java.lang.classfile.*; import jdk.internal.classfile.impl.AbstractInstruction; import jdk.internal.classfile.impl.Util; /** * Models a branching instruction (conditional or unconditional) in the {@code - * code} array of a {@code Code} attribute. Corresponding opcodes will have a - * {@code kind} of {@link Opcode.Kind#BRANCH}. Delivered as a {@link - * CodeElement} when traversing the elements of a {@link CodeModel}. + * code} array of a {@code Code} attribute. Corresponding opcodes have a + * {@linkplain Opcode#kind() kind} of {@link Opcode.Kind#BRANCH}. Delivered as + * a {@link CodeElement} when traversing the elements of a {@link CodeModel}. + *

    + * A branch instruction is composite: + * {@snippet lang=text : + * // @link substring="BranchInstruction" target="#of": + * BranchInstruction( + * Opcode opcode, // @link substring="opcode" target="#opcode()" + * Label target // @link substring="target" target="#target()" + * ) + * } + *

    + * Due to physical restrictions, some types of instructions cannot encode labels + * too far away in the list of code elements. In such cases, the {@link + * ClassFile.ShortJumpsOption} controls how an invalid branch instruction model + * is written by a {@link CodeBuilder}. * + * @see Opcode.Kind#BRANCH + * @see CodeBuilder#branch CodeBuilder::branch + * @see ClassFile.ShortJumpsOption * @since 24 */ public sealed interface BranchInstruction extends Instruction permits AbstractInstruction.BoundBranchInstruction, AbstractInstruction.UnboundBranchInstruction { /** - * {@return the target of the branch} + * {@return the branch target of this instruction} */ Label target(); @@ -56,7 +69,7 @@ public sealed interface BranchInstruction extends Instruction * which must be of kind {@link Opcode.Kind#BRANCH} * @param target the target of the branch * @throws IllegalArgumentException if the opcode kind is not - * {@link Opcode.Kind#BRANCH}. + * {@link Opcode.Kind#BRANCH} */ static BranchInstruction of(Opcode op, Label target) { Util.checkKind(op, Opcode.Kind.BRANCH); diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/CharacterRange.java b/src/java.base/share/classes/java/lang/classfile/instruction/CharacterRange.java index d47639d7dd7..07d4c116b3a 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/CharacterRange.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/CharacterRange.java @@ -25,6 +25,7 @@ package java.lang.classfile.instruction; import java.lang.classfile.ClassFile; +import java.lang.classfile.CodeBuilder; import java.lang.classfile.CodeElement; import java.lang.classfile.CodeModel; import java.lang.classfile.Label; @@ -36,11 +37,31 @@ import jdk.internal.classfile.impl.BoundCharacterRange; /** - * A pseudo-instruction which models a single entry in the - * {@link CharacterRangeTableAttribute}. Delivered as a {@link CodeElement} - * during traversal of the elements of a {@link CodeModel}, according to - * the setting of the {@link ClassFile.DebugElementsOption} option. + * A pseudo-instruction which models a single entry in the {@link + * CharacterRangeTableAttribute CharacterRangeTable} attribute. Delivered as a + * {@link CodeElement} during traversal of the elements of a {@link CodeModel}, + * according to the setting of the {@link ClassFile.DebugElementsOption} option. + *

    + * A character range entry is composite: + * {@snippet lang=text : + * // @link substring="CharacterRange" target="#of": + * CharacterRange( + * Label startScope, // @link substring="startScope" target="#startScope" + * Label endScope, // @link substring="endScope" target="#endScope" + * int characterRangeStart, // @link substring="characterRangeStart" target="#characterRangeStart" + * int characterRangeEnd, // @link substring="characterRangeEnd" target="#characterRangeEnd" + * int flags // @link substring="flags" target="#flags" + * ) + * } + *

    + * Another model, {@link CharacterRangeInfo}, also models a character range + * entry; it has no dependency on a {@code CodeModel} and represents of bci + * values as {@code int}s instead of {@code Label}s, and is used as components + * of a {@link CharacterRangeTableAttribute}. * + * @see CharacterRangeInfo + * @see CodeBuilder#characterRange CodeBuilder::characterRange + * @see ClassFile.DebugElementsOption * @since 24 */ public sealed interface CharacterRange extends PseudoInstruction @@ -114,7 +135,7 @@ public sealed interface CharacterRange extends PseudoInstruction *

  • {@link #FLAG_BRANCH_FALSE} *
* - * @see java.lang.classfile.attribute.CharacterRangeInfo#flags() + * @see CharacterRangeInfo#flags() * * @return the flags */ diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/ConstantInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/ConstantInstruction.java index 312c1868f19..f11a90c7d4c 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/ConstantInstruction.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/ConstantInstruction.java @@ -24,6 +24,7 @@ */ package java.lang.classfile.instruction; +import java.lang.classfile.CodeBuilder; import java.lang.classfile.CodeElement; import java.lang.classfile.CodeModel; import java.lang.classfile.Instruction; @@ -38,12 +39,22 @@ /** * Models a constant-load instruction in the {@code code} array of a {@code - * Code} attribute, including "intrinsic constant" instructions (e.g., {@code - * iconst_0}), "argument constant" instructions (e.g., {@code bipush}), and "load - * constant" instructions (e.g., {@code LDC}). Corresponding opcodes will have - * a {@code kind} of {@link Opcode.Kind#CONSTANT}. Delivered as a {@link - * CodeElement} when traversing the elements of a {@link CodeModel}. + * Code} attribute, including {@linkplain IntrinsicConstantInstruction + * "intrinsic"}, {@linkplain ArgumentConstantInstruction "argument"}, and + * {@linkplain LoadConstantInstruction "load"} constant instructions. + * Corresponding opcodes have a {@linkplain Opcode#kind() kind} of {@link + * Opcode.Kind#CONSTANT}. Delivered as a {@link CodeElement} when traversing + * the elements of a {@link CodeModel}. + *

+ * The loaded constant value is symbolically represented as a {@link ConstantDesc}: + * {@snippet lang=text : + * // @link substring="ConstantInstruction" target="CodeBuilder#loadConstant(ConstantDesc)" : + * ConstantInstruction(ConstantDesc constantValue) // @link substring="constantValue" target="#constantValue()" + * } * + * @see Opcode.Kind#CONSTANT + * @see CodeBuilder#loadConstant(ConstantDesc) CodeBuilder::loadConstant + * @sealedGraph * @since 24 */ public sealed interface ConstantInstruction extends Instruction { @@ -54,22 +65,36 @@ public sealed interface ConstantInstruction extends Instruction { ConstantDesc constantValue(); /** - * {@return the type of the constant} + * {@return the {@linkplain TypeKind##computational-type computational type} of the constant} + * This is derived from the {@link #constantValue() constantValue}. */ TypeKind typeKind(); /** - * Models an "intrinsic constant" instruction (e.g., {@code - * iconst_0}). + * Models an "intrinsic constant" instruction, which encodes + * the constant value in its opcode. Examples include {@link + * Opcode#ACONST_NULL aconst_null} and {@link + * Opcode#ICONST_0 iconst_0}. + *

+ * An intrinsic constant instruction is composite: + * {@snippet lang=text : + * // @link substring="IntrinsicConstantInstruction" target="#ofIntrinsic" : + * IntrinsicConstantInstruction(Opcode opcode) // @link substring="opcode" target="#opcode()" + * } + * where: + *

+ *
{@link #opcode() opcode}
+ *
Must be of the constant kind and have a {@linkplain + * Opcode#sizeIfFixed() fixed size} of 1.
+ *
* + * @see Opcode.Kind#CONSTANT + * @see ConstantInstruction#ofIntrinsic ConstantInstruction::ofIntrinsic * @since 24 */ sealed interface IntrinsicConstantInstruction extends ConstantInstruction permits AbstractInstruction.UnboundIntrinsicConstantInstruction { - /** - * {@return the type of the constant} - */ @Override default TypeKind typeKind() { return BytecodeHelpers.intrinsicConstantType(opcode()); @@ -77,9 +102,31 @@ default TypeKind typeKind() { } /** - * Models an "argument constant" instruction (e.g., {@code - * bipush}). + * Models an "argument constant" instruction, which encodes the + * constant value in the instruction directly. Includes {@link + * Opcode#BIPUSH bipush} and {@link Opcode#SIPUSH sipush} instructions. + *

+ * An argument constant instruction is composite: + * {@snippet lang=text : + * // @link substring="ArgumentConstantInstruction" target="#ofArgument" : + * ArgumentConstantInstruction( + * Opcode opcode, // @link substring="opcode" target="#opcode()" + * int constantValue // @link substring="constantValue" target="#constantValue()" + * ) + * } + * where: + *

    + *
  • {@code opcode} must be one of {@code bipush} or {@code sipush}. + *
  • {@code constantValue} must be in the range of {@code byte}, {@code + * [-128, 127]}, for {@code bipush}, and in the range of {@code short}, + * {@code [-32768, 32767]}, for {@code sipush}. + *
* + * @see Opcode.Kind#CONSTANT + * @see ConstantInstruction#ofArgument ConstantInstruction::ofArgument + * @see CodeBuilder#loadConstant(int) CodeBuilder::loadConstant(int) + * @see CodeBuilder#bipush CodeBuilder::bipush + * @see CodeBuilder#sipush CodeBuilder::sipush * @since 24 */ sealed interface ArgumentConstantInstruction extends ConstantInstruction @@ -89,9 +136,6 @@ sealed interface ArgumentConstantInstruction extends ConstantInstruction @Override Integer constantValue(); - /** - * {@return the type of the constant} - */ @Override default TypeKind typeKind() { return TypeKind.INT; @@ -99,9 +143,24 @@ default TypeKind typeKind() { } /** - * Models a "load constant" instruction (e.g., {@code - * ldc}). + * Models a "load constant" instruction, which encodes the constant value + * in the constant pool. Includes {@link Opcode#LDC ldc} and {@link + * Opcode#LDC_W ldc_w}, and {@link Opcode#LDC2_W ldc2_w} instructions. + *

+ * A load constant instruction is composite: + * {@snippet lang=text : + * // @link substring="LoadConstantInstruction" target="CodeBuilder#ldc(LoadableConstantEntry)" : + * LoadConstantInstruction(LoadableConstantEntry constantEntry) // @link substring="constantEntry" target="#constantEntry()" + * } + *

+ * A "load constant" instruction can load any constant value supported by + * other constant-load instructions. However, other instructions are + * usually more optimized, avoiding extra constant pool entries and being + * smaller. * + * @see Opcode.Kind#CONSTANT + * @see ConstantInstruction#ofLoad ConstantInstruction::ofLoad + * @see CodeBuilder#ldc CodeBuilder::ldc * @since 24 */ sealed interface LoadConstantInstruction extends ConstantInstruction @@ -113,9 +172,6 @@ sealed interface LoadConstantInstruction extends ConstantInstruction */ LoadableConstantEntry constantEntry(); - /** - * {@return the type of the constant} - */ @Override default TypeKind typeKind() { return constantEntry().typeKind(); @@ -139,6 +195,10 @@ static IntrinsicConstantInstruction ofIntrinsic(Opcode op) { /** * {@return an argument constant instruction} + *

+ * {@code value} must be in the range of {@code byte}, {@code [-128, 127]}, + * for {@link Opcode#BIPUSH}, and in the range of {@code short}, {@code + * [-32768, 32767]}, for {@link Opcode#SIPUSH}. * * @param op the opcode for the specific type of argument constant instruction, * which must be {@link Opcode#BIPUSH} or {@link Opcode#SIPUSH} diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/ConvertInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/ConvertInstruction.java index 468685779b9..0edffda1af1 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/ConvertInstruction.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/ConvertInstruction.java @@ -24,6 +24,7 @@ */ package java.lang.classfile.instruction; +import java.lang.classfile.CodeBuilder; import java.lang.classfile.CodeElement; import java.lang.classfile.CodeModel; import java.lang.classfile.Instruction; @@ -36,10 +37,27 @@ /** * Models a primitive conversion instruction in the {@code code} array of a - * {@code Code} attribute, such as {@code i2l}. Corresponding opcodes will have - * a {@code kind} of {@link Opcode.Kind#CONVERT}. Delivered as a {@link - * CodeElement} when traversing the elements of a {@link CodeModel}. + * {@code Code} attribute, such as {@link Opcode#I2L i2l}. Corresponding opcodes + * have a {@linkplain Opcode#kind() kind} of {@link Opcode.Kind#CONVERT}. + * Delivered as a {@link CodeElement} when traversing the elements of a {@link CodeModel}. + *

+ * A primitive conversion instruction is composite: + * {@snippet lang=text : + * // @link substring="ConvertInstruction" target="#of(TypeKind, TypeKind)" : + * ConvertInstruction( + * TypeKind fromType, // @link substring="fromType" target="#fromType" + * TypeKind toType // @link substring="toType" target="#toType" + * ) + * } + * where these conversions are valid: + *

    + *
  • Between {@code int}, {@code long}, {@code float}, and {@code double}, where + * {@code fromType != toType}; + *
  • From {@code int} to {@code byte}, {@code char}, and {@code short}. + *
* + * @see Opcode.Kind#CONVERT + * @see CodeBuilder#conversion CodeBuilder::conversion * @since 24 */ public sealed interface ConvertInstruction extends Instruction @@ -55,10 +73,16 @@ public sealed interface ConvertInstruction extends Instruction TypeKind toType(); /** - * {@return A conversion instruction} + * {@return a conversion instruction} Valid conversions are: + *
    + *
  • Between {@code int}, {@code long}, {@code float}, and {@code double}, + * where {@code fromType != toType}; + *
  • From {@code int} to {@code byte}, {@code char}, and {@code short}. + *
* * @param fromType the type to convert from * @param toType the type to convert to + * @throws IllegalArgumentException if this is not a valid conversion */ static ConvertInstruction of(TypeKind fromType, TypeKind toType) { return of(BytecodeHelpers.convertOpcode(fromType, toType)); diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/DiscontinuedInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/DiscontinuedInstruction.java index 4e8ddcef385..4170e142ffe 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/DiscontinuedInstruction.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/DiscontinuedInstruction.java @@ -24,32 +24,54 @@ */ package java.lang.classfile.instruction; -import java.lang.classfile.CodeElement; -import java.lang.classfile.CodeModel; -import java.lang.classfile.Instruction; -import java.lang.classfile.Label; -import java.lang.classfile.Opcode; +import java.lang.classfile.*; import jdk.internal.classfile.impl.AbstractInstruction; import jdk.internal.classfile.impl.BytecodeHelpers; import jdk.internal.classfile.impl.Util; /** - * Models instruction discontinued from the {@code code} array of a {@code Code} - * attribute. Delivered as a {@link CodeElement} when traversing the elements of - * a {@link CodeModel}. + * Marker interface for instruction discontinued from the {@code code} array of + * a {@code Code} attribute. Delivered as a {@link CodeElement} when traversing + * the elements of a {@link CodeModel}. * + * @apiNote + * While most instructions have convenience factory methods in {@link + * CodeBuilder}, discontinued instructions can only be supplied to code builders + * explicitly with {@link CodeBuilder#with CodeBuilder::with} to discourage + * their use. + * + * @jvms 4.9.1 Static Constraints + * @sealedGraph * @since 24 */ public sealed interface DiscontinuedInstruction extends Instruction { /** - * Models JSR and JSR_W instructions discontinued from the {@code code} - * array of a {@code Code} attribute since class file version 51.0. - * Corresponding opcodes will have a {@code kind} of - * {@link Opcode.Kind#DISCONTINUED_JSR}. Delivered as a {@link CodeElement} - * when traversing the elements of a {@link CodeModel}. + * Models jump subroutine instructions discontinued from the {@code code} + * array of a {@code Code} attribute since class file major version {@value + * ClassFile#JAVA_7_VERSION} (JVMS {@jvms 4.9.1}). Corresponding opcodes + * have a {@linkplain Opcode#kind() kind} of {@link Opcode.Kind#DISCONTINUED_JSR}. + * Delivered as a {@link CodeElement} when traversing the elements of a + * {@link CodeModel}. + *

+ * A jump subroutine instruction is composite: + * {@snippet lang=text : + * // @link substring="JsrInstruction" target="#of(Label)" : + * JsrInstruction(Label target) // @link substring="target" target="#target()" + * } + *

+ * Due to physical restrictions, {@link Opcode#JSR jsr} instructions cannot + * encode labels too far away in the list of code elements. In such cases, + * the {@link ClassFile.ShortJumpsOption} controls how an invalid {@code jsr} + * instruction model is written by a {@link CodeBuilder}. + *

+ * Jump subroutine instructions push a {@link TypeKind##returnAddress + * returnAddress} value to the operand stack, and {@link StoreInstruction + * astore} series of instructions can then store this value to a local + * variable slot. * + * @see Opcode.Kind#DISCONTINUED_JSR * @since 24 */ sealed interface JsrInstruction extends DiscontinuedInstruction @@ -57,14 +79,18 @@ sealed interface JsrInstruction extends DiscontinuedInstruction AbstractInstruction.UnboundJsrInstruction { /** - * {@return the target of the JSR instruction} + * {@return the target of the jump subroutine instruction} */ Label target(); /** - * {@return a JSR instruction} + * {@return a jump subroutine instruction} * - * @param op the opcode for the specific type of JSR instruction, + * @apiNote + * The explicit {@code op} argument allows creating {@link Opcode#JSR_W + * jsr_w} instructions to avoid short jumps. + * + * @param op the opcode for the specific type of jump subroutine instruction, * which must be of kind {@link Opcode.Kind#DISCONTINUED_JSR} * @param target target label of the subroutine * @throws IllegalArgumentException if the opcode kind is not @@ -76,7 +102,7 @@ static JsrInstruction of(Opcode op, Label target) { } /** - * {@return a JSR instruction} + * {@return a jump subroutine instruction} * * @param target target label of the subroutine */ @@ -86,12 +112,26 @@ static JsrInstruction of(Label target) { } /** - * Models RET and RET_W instructions discontinued from the {@code code} - * array of a {@code Code} attribute since class file version 51.0. - * Corresponding opcodes will have a {@code kind} of + * Models return from subroutine instructions discontinued from the {@code + * code} array of a {@code Code} attribute since class file major version + * {@value ClassFile#JAVA_7_VERSION} (JVMS {@jvms 4.9.1}). + * Corresponding opcodes have a {@linkplain Opcode#kind() kind} of * {@link Opcode.Kind#DISCONTINUED_RET}. Delivered as a {@link CodeElement} * when traversing the elements of a {@link CodeModel}. + *

+ * A return from subroutine instruction is composite: + * {@snippet lang=text : + * // @link substring="RetInstruction" target="#of(int)" : + * RetInstruction(int slot) // @link substring="slot" target="#slot()" + * } + * where {@code slot} must be within {@code [0, 65535]}. + *

+ * {@link StoreInstruction astore} series of instructions store a {@link + * TypeKind##returnAddress returnAddress} value to a local variable slot, + * making the slot usable by a return from subroutine instruction. * + * @jvms 6.5.ret ret + * @see Opcode.Kind#DISCONTINUED_RET * @since 24 */ sealed interface RetInstruction extends DiscontinuedInstruction @@ -100,13 +140,23 @@ sealed interface RetInstruction extends DiscontinuedInstruction /** * {@return the local variable slot with return address} + * The value is within {@code [0, 65535]}. */ int slot(); /** - * {@return a RET or RET_W instruction} + * {@return a return from subroutine instruction} + *

+ * {@code slot} must be in the closed range of {@code [0, 255]} for + * {@link Opcode#RET ret}, or within {@code [0, 65535]} for {@link + * Opcode#RET_W wide ret}. + * + * @apiNote + * The explicit {@code op} argument allows creating {@code wide ret} + * instructions with {@code slot} in the range of regular {@code ret} + * instructions. * - * @param op the opcode for the specific type of RET instruction, + * @param op the opcode for the specific type of return from subroutine instruction, * which must be of kind {@link Opcode.Kind#DISCONTINUED_RET} * @param slot the local variable slot to load return address from * @throws IllegalArgumentException if the opcode kind is not @@ -118,7 +168,9 @@ static RetInstruction of(Opcode op, int slot) { } /** - * {@return a RET instruction} + * {@return a return from subroutine instruction} + *

+ * {@code slot} must be within {@code [0, 65535]}. * * @param slot the local variable slot to load return address from * @throws IllegalArgumentException if {@code slot} is out of range diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/ExceptionCatch.java b/src/java.base/share/classes/java/lang/classfile/instruction/ExceptionCatch.java index 885f029d108..2a86c4bd09c 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/ExceptionCatch.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/ExceptionCatch.java @@ -24,23 +24,37 @@ */ package java.lang.classfile.instruction; +import java.lang.classfile.CodeBuilder; import java.lang.classfile.CodeElement; import java.lang.classfile.CodeModel; import java.lang.classfile.Label; import java.lang.classfile.PseudoInstruction; +import java.lang.classfile.attribute.CodeAttribute; import java.lang.classfile.constantpool.ClassEntry; import java.util.Optional; import jdk.internal.classfile.impl.AbstractPseudoInstruction; /** - * A pseudo-instruction modeling an entry in the exception table of a code - * attribute. Entries in the exception table model catch and finally blocks. - * Delivered as a {@link CodeElement} when traversing the contents - * of a {@link CodeModel}. - * - * @see PseudoInstruction + * A pseudo-instruction modeling an entry in the {@code exception_table} array + * of a {@link CodeAttribute Code} attribute. Catch (JVMS {@jvms 3.12}) and + * finally (JVMS {@jvms 3.14}) blocks in Java source code compile to exception + * table entries. Delivered as a {@link CodeElement} when traversing the + * contents of a {@link CodeModel}. + *

+ * An exception table entry is composite: + * {@snippet lang=text : + * // @link substring="ExceptionCatch" target="#of(Label, Label, Label, Optional)" : + * ExceptionCatch( + * Label handler, // @link substring="handler" target="#handler" + * Label tryStart, // @link substring="tryStart" target="#tryStart" + * Label tryEnd, // @link substring="tryEnd" target="#tryEnd" + * Optional catchType // @link substring="catchType" target="#catchType" + * ) + * } * + * @see CodeBuilder#exceptionCatch CodeBuilder::exceptionCatch + * @jvms 4.7.3 The {@code Code} Attribute * @since 24 */ public sealed interface ExceptionCatch extends PseudoInstruction @@ -61,8 +75,8 @@ public sealed interface ExceptionCatch extends PseudoInstruction Label tryEnd(); /** - * {@return the type of the exception to catch, or empty if this handler is - * unconditional} + * {@return the type of the exception to catch, or empty if this handler + * catches everything} */ Optional catchType(); @@ -80,10 +94,10 @@ static ExceptionCatch of(Label handler, Label tryStart, Label tryEnd, } /** - * {@return an exception table pseudo-instruction for an unconditional handler} + * {@return an exception table pseudo-instruction to catch everything} * @param handler the handler for the exception - * @param tryStart the beginning of the instruction range for the gaurded instructions - * @param tryEnd the end of the instruction range for the gaurded instructions + * @param tryStart the beginning of the instruction range for the guarded instructions + * @param tryEnd the end of the instruction range for the guarded instructions */ static ExceptionCatch of(Label handler, Label tryStart, Label tryEnd) { return new AbstractPseudoInstruction.ExceptionCatchImpl(handler, tryStart, tryEnd, (ClassEntry) null); diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/FieldInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/FieldInstruction.java index b547abd18ab..68d56667957 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/FieldInstruction.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/FieldInstruction.java @@ -24,6 +24,7 @@ */ package java.lang.classfile.instruction; +import java.lang.classfile.CodeBuilder; import java.lang.classfile.CodeElement; import java.lang.classfile.CodeModel; import java.lang.classfile.Instruction; @@ -40,10 +41,21 @@ /** * Models a field access instruction in the {@code code} array of a {@code Code} - * attribute. Corresponding opcodes will have a {@code kind} of {@link - * Opcode.Kind#FIELD_ACCESS}. Delivered as a {@link CodeElement} when + * attribute. Corresponding opcodes have a {@linkplain Opcode#kind() kind} + * of {@link Opcode.Kind#FIELD_ACCESS}. Delivered as a {@link CodeElement} when * traversing the elements of a {@link CodeModel}. + *

+ * A field access instruction is composite: + * {@snippet lang=text : + * // @link substring="FieldInstruction" target="#of(Opcode, FieldRefEntry)" : + * FieldInstruction( + * Opcode opcode, // @link substring="opcode" target="#opcode()" + * FieldRefEntry field, // @link substring="field" target="#field()" + * ) + * } * + * @see Opcode.Kind#FIELD_ACCESS + * @see CodeBuilder#fieldAccess CodeBuilder::fieldAccess * @since 24 */ public sealed interface FieldInstruction extends Instruction @@ -68,7 +80,11 @@ default Utf8Entry name() { } /** - * {@return the field descriptor of the field} + * {@return the field descriptor string of the field} + * + * @apiNote + * A symbolic descriptor for the type of the field is available through + * {@link #typeSymbol() typeSymbol()}. */ default Utf8Entry type() { return field().nameAndType().type(); @@ -103,6 +119,8 @@ static FieldInstruction of(Opcode op, FieldRefEntry field) { * @param owner the class holding the field * @param name the name of the field * @param type the field descriptor + * @throws IllegalArgumentException if the opcode kind is not + * {@link Opcode.Kind#FIELD_ACCESS}. */ static FieldInstruction of(Opcode op, ClassEntry owner, @@ -118,6 +136,8 @@ static FieldInstruction of(Opcode op, * which must be of kind {@link Opcode.Kind#FIELD_ACCESS} * @param owner the class holding the field * @param nameAndType the name and field descriptor of the field + * @throws IllegalArgumentException if the opcode kind is not + * {@link Opcode.Kind#FIELD_ACCESS}. */ static FieldInstruction of(Opcode op, ClassEntry owner, diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/IncrementInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/IncrementInstruction.java index 7ea516c7cc5..a874ef0a954 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/IncrementInstruction.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/IncrementInstruction.java @@ -24,6 +24,7 @@ */ package java.lang.classfile.instruction; +import java.lang.classfile.CodeBuilder; import java.lang.classfile.CodeElement; import java.lang.classfile.CodeModel; import java.lang.classfile.Instruction; @@ -33,10 +34,27 @@ /** * Models a local variable increment instruction in the {@code code} array of a - * {@code Code} attribute. Corresponding opcodes will have a {@code kind} of - * {@link Opcode.Kind#INCREMENT}. Delivered as a {@link CodeElement} when + * {@code Code} attribute. Corresponding opcodes have a {@linkplain Opcode#kind() + * kind} of {@link Opcode.Kind#INCREMENT}. Delivered as a {@link CodeElement} when * traversing the elements of a {@link CodeModel}. + *

+ * A local variable increment instruction is composite: + * {@snippet lang=text : + * // @link substring="IncrementInstruction" target="#of" : + * IncrementInstruction( + * int slot, // @link substring="slot" target="#slot()" + * int constant // @link substring="constant" target="#constant()" + * ) + * } + * where + *

    + *
  • {@code slot} must be within {@code [0, 65535]}. + *
  • {@code constant} must be within {@code [-32768, 32767]}. + *
* + * @see Opcode.Kind#INCREMENT + * @see CodeBuilder#iinc CodeBuilder::iinc + * @jvms 6.5.iinc iinc * @since 24 */ public sealed interface IncrementInstruction extends Instruction @@ -54,6 +72,10 @@ public sealed interface IncrementInstruction extends Instruction /** * {@return an increment instruction} + *
    + *
  • {@code slot} must be within {@code [0, 65535]}. + *
  • {@code constant} must be within {@code [-32768, 32767]}. + *
* * @param slot the local variable slot to increment * @param constant the value to increment by diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/InvokeDynamicInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/InvokeDynamicInstruction.java index 43907b2a518..7cad91b9d8d 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/InvokeDynamicInstruction.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/InvokeDynamicInstruction.java @@ -24,9 +24,11 @@ */ package java.lang.classfile.instruction; +import java.lang.classfile.CodeBuilder; import java.lang.classfile.CodeElement; import java.lang.classfile.CodeModel; import java.lang.classfile.Instruction; +import java.lang.classfile.Opcode; import java.lang.classfile.constantpool.InvokeDynamicEntry; import java.lang.classfile.constantpool.LoadableConstantEntry; import java.lang.classfile.constantpool.Utf8Entry; @@ -40,10 +42,20 @@ import jdk.internal.classfile.impl.Util; /** - * Models an {@code invokedynamic} instruction in the {@code code} array of a - * {@code Code} attribute. Delivered as a {@link CodeElement} when traversing - * the elements of a {@link CodeModel}. + * Models a dynamically-computed call site invocation instruction in the + * {@code code} array of a {@code Code} attribute. The corresponding opcode is + * {@link Opcode#INVOKEDYNAMIC invokedynamic}. Delivered as a {@link + * CodeElement} when traversing the elements of a {@link CodeModel}. + *

+ * A dynamically-computed call site invocation instruction is composite: + * {@snippet lang=text : + * // @link substring="InvokeDynamicInstruction" target="#of" : + * InvokeDynamicInstruction(InvokeDynamicEntry invokedynamic) // @link substring="invokedynamic" target="#invokedynamic()" + * } * + * @see Opcode.Kind#INVOKE_DYNAMIC + * @see CodeBuilder#invokedynamic CodeBuilder::invokedynamic + * @jvms 6.5.invokedynamic invokedynamic * @since 24 */ public sealed interface InvokeDynamicInstruction extends Instruction @@ -62,6 +74,10 @@ default Utf8Entry name() { /** * {@return the invocation type of the call site} + * + * @apiNote + * A symbolic descriptor for the invocation typeis available through {@link + * #typeSymbol() typeSymbol()}. */ default Utf8Entry type() { return invokedynamic().type(); diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/InvokeInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/InvokeInstruction.java index 904a17375ac..50791cbd0ff 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/InvokeInstruction.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/InvokeInstruction.java @@ -24,10 +24,12 @@ */ package java.lang.classfile.instruction; +import java.lang.classfile.CodeBuilder; import java.lang.classfile.CodeElement; import java.lang.classfile.CodeModel; import java.lang.classfile.Instruction; import java.lang.classfile.Opcode; +import java.lang.classfile.TypeKind; import java.lang.classfile.constantpool.ClassEntry; import java.lang.classfile.constantpool.InterfaceMethodRefEntry; import java.lang.classfile.constantpool.MemberRefEntry; @@ -42,10 +44,26 @@ /** * Models a method invocation instruction in the {@code code} array of a {@code - * Code} attribute, other than {@code invokedynamic}. Corresponding opcodes - * will have a {@code kind} of {@link Opcode.Kind#INVOKE}. Delivered as a - * {@link CodeElement} when traversing the elements of a {@link CodeModel}. + * Code} attribute, other than {@link InvokeDynamicInstruction invokedynamic}. + * Corresponding opcodes have a {@linkplain Opcode#kind() kind} of {@link Opcode.Kind#INVOKE}. + * Delivered as a {@link CodeElement} when traversing the elements of a {@link CodeModel}. + *

+ * A method invocation instruction is composite: + * {@snippet lang=text : + * // @link substring="InvokeInstruction" target="#of(Opcode, MemberRefEntry)" : + * InvokeInstruction( + * Opcode opcode, // @link substring="opcode" target="#opcode()" + * MethodRefEntry | InterfaceMethodRefEntry method) // @link substring="method" target="#method()" + * ) + * } + * where {@code method} must be an {@code InterfaceMethodRefEntry} for {@link + * Opcode#INVOKEINTERFACE invokeinterface} opcode, and must be a {@code + * MethodRefEntry} for {@link Opcode#INVOKEVIRTUAL invokevirtual} opcode. + * {@link Opcode#INVOKESTATIC invokestatic} and {@link Opcode#INVOKESPECIAL + * invokespecial} can have either type of entry for {@code method}. * + * @see Opcode.Kind#INVOKE + * @see CodeBuilder#invoke CodeBuilder::invoke * @since 24 */ public sealed interface InvokeInstruction extends Instruction @@ -57,18 +75,25 @@ public sealed interface InvokeInstruction extends Instruction MemberRefEntry method(); /** - * {@return whether the class holding the method is an interface} + * {@return whether the class or interface holding the method is an interface} */ boolean isInterface(); /** - * {@return the {@code count} value of an {@code invokeinterface} instruction, as defined in JVMS {@jvms 6.5} - * or {@code 0} for {@code invokespecial}, {@code invokestatic} and {@code invokevirtual} instructions} + * {@return the {@code count} value of an {@code invokeinterface} instruction, + * or {@code 0} for other instructions} + *

+ * For an {@code invokeinterface} instruction, this value must be equivalent + * to the sum of {@linkplain TypeKind#slotSize() slot sizes} of all arguments + * plus one, which is equal to the number of operand stack depth consumed by + * this interface method invocation instruction. + * + * @jvms 6.5.invokeinterface invokeinterface */ int count(); /** - * {@return the class holding the method} + * {@return the class or interface holding the method} */ default ClassEntry owner() { return method().owner(); @@ -82,7 +107,11 @@ default Utf8Entry name() { } /** - * {@return the method descriptor of the method} + * {@return the method descriptor string of the method} + * + * @apiNote + * A symbolic descriptor for the type of the method is available through + * {@link #typeSymbol() typeSymbol()}. */ default Utf8Entry type() { return method().nameAndType().type(); @@ -95,7 +124,6 @@ default MethodTypeDesc typeSymbol() { return Util.methodTypeSymbol(method().type()); } - /** * {@return an invocation instruction} * @@ -103,7 +131,7 @@ default MethodTypeDesc typeSymbol() { * which must be of kind {@link Opcode.Kind#INVOKE} * @param method a constant pool entry describing the method * @throws IllegalArgumentException if the opcode kind is not - * {@link Opcode.Kind#INVOKE}. + * {@link Opcode.Kind#INVOKE} */ static InvokeInstruction of(Opcode op, MemberRefEntry method) { Util.checkKind(op, Opcode.Kind.INVOKE); @@ -119,6 +147,8 @@ static InvokeInstruction of(Opcode op, MemberRefEntry method) { * @param name the name of the method * @param type the method descriptor * @param isInterface whether the class holding the method is an interface + * @throws IllegalArgumentException if the opcode kind is not + * {@link Opcode.Kind#INVOKE} */ static InvokeInstruction of(Opcode op, ClassEntry owner, @@ -136,6 +166,8 @@ static InvokeInstruction of(Opcode op, * @param owner the class holding the method * @param nameAndType the name and type of the method * @param isInterface whether the class holding the method is an interface + * @throws IllegalArgumentException if the opcode kind is not + * {@link Opcode.Kind#INVOKE} */ static InvokeInstruction of(Opcode op, ClassEntry owner, diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/LabelTarget.java b/src/java.base/share/classes/java/lang/classfile/instruction/LabelTarget.java index bc1deffc98b..94ac1839c75 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/LabelTarget.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/LabelTarget.java @@ -24,10 +24,13 @@ */ package java.lang.classfile.instruction; +import java.lang.classfile.CodeBuilder; import java.lang.classfile.CodeElement; import java.lang.classfile.CodeModel; +import java.lang.classfile.CodeTransform; import java.lang.classfile.Label; import java.lang.classfile.PseudoInstruction; +import java.lang.classfile.attribute.CodeAttribute; import jdk.internal.classfile.impl.LabelImpl; @@ -35,9 +38,28 @@ * A pseudo-instruction which indicates that the specified label corresponds to * the current position in the {@code Code} attribute. Delivered as a {@link * CodeElement} during traversal of the elements of a {@link CodeModel}. + *

+ * This can be used to inspect the target position of labels across {@linkplain + * CodeTransform transformations}, as {@linkplain CodeAttribute#labelToBci bci} + * is not stable. + *

+ * When passed to a {@link CodeBuilder}, this pseudo-instruction sets the + * specified label to be bound at the current position in the builder. + *

+ * By design, {@code LabelTarget} cannot be created by users and can only be + * read from a code model. Use {@link CodeBuilder#labelBinding + * CodeBuilder::labelBinding} to bind arbitrary labels to a {@code CodeBuilder}. + *

+ * For a {@code CodeBuilder cob}, a {@code LabelTarget lt}, these two calls are + * equivalent: + * {@snippet lang=java : + * cob.with(lt); // @link substring="with" target="CodeBuilder#with" + * // @link substring="labelBinding" target="CodeBuilder#labelBinding" : + * cob.labelBinding(lt.label()); // @link regex="label(?=\()" target="#label" + * } * - * @see PseudoInstruction - * + * @see Label + * @see CodeBuilder#labelBinding CodeBuilder::labelBinding * @since 24 */ public sealed interface LabelTarget extends PseudoInstruction diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/LineNumber.java b/src/java.base/share/classes/java/lang/classfile/instruction/LineNumber.java index a9a497708c0..3f10a3ada0d 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/LineNumber.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/LineNumber.java @@ -25,21 +25,42 @@ package java.lang.classfile.instruction; import java.lang.classfile.ClassFile; +import java.lang.classfile.CodeBuilder; import java.lang.classfile.CodeElement; import java.lang.classfile.CodeModel; import java.lang.classfile.PseudoInstruction; +import java.lang.classfile.attribute.CodeAttribute; +import java.lang.classfile.attribute.LineNumberInfo; import java.lang.classfile.attribute.LineNumberTableAttribute; import jdk.internal.classfile.impl.LineNumberImpl; /** - * A pseudo-instruction which models a single entry in the - * {@link LineNumberTableAttribute}. Delivered as a {@link CodeElement} - * during traversal of the elements of a {@link CodeModel}, according to - * the setting of the {@link ClassFile.LineNumbersOption} option. + * A pseudo-instruction which indicates the code for a given line number starts + * after the current position in a {@link CodeAttribute Code} attribute. This + * models a single entry in the {@link LineNumberTableAttribute LineNumberTable} + * attribute. Delivered as a {@link CodeElement} during traversal of the + * elements of a {@link CodeModel}, according to the setting of the {@link + * ClassFile.LineNumbersOption} option. + *

+ * A line number entry is composite: + * {@snippet lang=text : + * // @link substring="LineNumber" target="#of" : + * LineNumber(int line) // @link substring="int line" target="#line" + * } + *

+ * Another model, {@link LineNumberInfo}, also models a line number entry; it + * has no dependency on a {@code CodeModel} and represents of bci values as + * {@code int}s instead of order of pseudo-instructions in the elements of a + * {@code CodeModel}, and is used as components of a {@link LineNumberTableAttribute}. * - * @see PseudoInstruction + * @apiNote + * Line numbers are represented with custom pseudo-instructions to avoid using + * labels, which usually indicate branching targets for the control flow. * + * @see LineNumberInfo + * @see CodeBuilder#lineNumber CodeBuilder::lineNumber + * @see ClassFile.LineNumbersOption * @since 24 */ public sealed interface LineNumber extends PseudoInstruction diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/LoadInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/LoadInstruction.java index c499dcc9944..81961320be3 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/LoadInstruction.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/LoadInstruction.java @@ -24,6 +24,7 @@ */ package java.lang.classfile.instruction; +import java.lang.classfile.CodeBuilder; import java.lang.classfile.CodeElement; import java.lang.classfile.CodeModel; import java.lang.classfile.Instruction; @@ -36,10 +37,23 @@ /** * Models a local variable load instruction in the {@code code} array of a - * {@code Code} attribute. Corresponding opcodes will have a {@code kind} of - * {@link Opcode.Kind#LOAD}. Delivered as a {@link CodeElement} when - * traversing the elements of a {@link CodeModel}. + * {@code Code} attribute. Corresponding opcodes have a {@linkplain + * Opcode#kind() kind} of {@link Opcode.Kind#LOAD}. Delivered as a {@link + * CodeElement} when traversing the elements of a {@link CodeModel}. + *

+ * A local variable load instruction is composite: + * {@snippet lang=text : + * // @link substring="LoadInstruction" target="#of(TypeKind, int)" : + * LoadInstruction( + * TypeKind typeKind, // @link substring="typeKind" target="#typeKind" + * int slot // @link substring="slot" target="#slot" + * ) + * } + * where {@code TypeKind} is {@linkplain TypeKind##computational-type + * computational}, and {@code slot} is within {@code [0, 65535]}. * + * @see Opcode.Kind#LOAD + * @see CodeBuilder#loadLocal CodeBuilder::loadLocal * @since 24 */ public sealed interface LoadInstruction extends Instruction @@ -48,16 +62,21 @@ public sealed interface LoadInstruction extends Instruction /** * {@return the local variable slot to load from} + * The value is within {@code [0, 65535]}. */ int slot(); /** - * {@return the type of the value to be loaded} + * {@return the {@linkplain TypeKind##computational-type computational type} + * of the value to be loaded} */ TypeKind typeKind(); /** * {@return a local variable load instruction} + * {@code kind} is {@linkplain TypeKind#asLoadable() converted} to its + * computational type. + * {@code slot} must be within {@code [0, 65535]}. * * @param kind the type of the value to be loaded * @param slot the local variable slot to load from @@ -71,6 +90,20 @@ static LoadInstruction of(TypeKind kind, int slot) { /** * {@return a local variable load instruction} + *

+ * The range of {@code slot} is restricted by the {@code op} and its + * {@linkplain Opcode#sizeIfFixed() size}: + *

    + *
  • If {@code op} has size 1, {@code slot} must be exactly the slot value + * implied by the opcode. + *
  • If {@code op} has size 2, {@code slot} must be within {@code [0, 255]}. + *
  • If {@code op} has size 4, {@code slot} must be within {@code [0, 65535]}. + *
+ * + * @apiNote + * The explicit {@code op} argument allows creating {@code wide} or + * regular load instructions when the {@code slot} can be encoded + * with more optimized load instructions. * * @param op the opcode for the specific type of load instruction, * which must be of kind {@link Opcode.Kind#LOAD} diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/LocalVariable.java b/src/java.base/share/classes/java/lang/classfile/instruction/LocalVariable.java index 0f8cb672e51..f44a4e094f1 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/LocalVariable.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/LocalVariable.java @@ -25,10 +25,12 @@ package java.lang.classfile.instruction; import java.lang.classfile.ClassFile; +import java.lang.classfile.CodeBuilder; import java.lang.classfile.CodeElement; import java.lang.classfile.CodeModel; import java.lang.classfile.Label; import java.lang.classfile.PseudoInstruction; +import java.lang.classfile.attribute.LocalVariableInfo; import java.lang.classfile.attribute.LocalVariableTableAttribute; import java.lang.classfile.constantpool.Utf8Entry; import java.lang.constant.ClassDesc; @@ -39,19 +41,45 @@ import jdk.internal.classfile.impl.Util; /** - * A pseudo-instruction which models a single entry in the - * {@link LocalVariableTableAttribute}. Delivered as a {@link CodeElement} - * during traversal of the elements of a {@link CodeModel}, according to - * the setting of the {@link ClassFile.DebugElementsOption} option. + * A pseudo-instruction which models a single entry in the {@link + * LocalVariableTableAttribute LocalVariableTable} attribute. Delivered as a + * {@link CodeElement} during traversal of the elements of a {@link CodeModel}, + * according to the setting of the {@link ClassFile.DebugElementsOption} option. + *

+ * A local variable entry is composite: + * {@snippet lang=text : + * // @link substring="LocalVariable" target="#of(int, String, ClassDesc, Label, Label)" : + * LocalVariable( + * int slot, // @link substring="slot" target="#slot" + * String name, // @link substring="name" target="#name" + * ClassDesc type, // @link substring="type" target="#type" + * Label startScope, // @link substring="startScope" target="#startScope" + * Label endScope // @link substring="endScope" target="#endScope" + * ) + * } + * Where {@code slot} is within {@code [0, 65535]}. + *

+ * Another model, {@link LocalVariableInfo}, also models a local variable + * entry; it has no dependency on a {@code CodeModel} and represents of bci + * values as {@code int}s instead of {@code Label}s, and is used as components + * of a {@link LocalVariableTableAttribute}. * - * @see PseudoInstruction + * @apiNote + * {@code LocalVariable} is used for all local variables in Java source code. + * If a local variable has a parameterized type, a type argument, or an array + * type of one of the previous types, a {@link LocalVariableType} should be + * created for that local variable as well. * + * @see LocalVariableInfo + * @see CodeBuilder#localVariable CodeBuilder::localVariable + * @see ClassFile.DebugElementsOption * @since 24 */ public sealed interface LocalVariable extends PseudoInstruction permits AbstractPseudoInstruction.UnboundLocalVariable, BoundLocalVariable { /** * {@return the local variable slot} + * The value is within {@code [0, 65535]}. */ int slot(); @@ -61,7 +89,11 @@ public sealed interface LocalVariable extends PseudoInstruction Utf8Entry name(); /** - * {@return the local variable field descriptor} + * {@return the local variable field descriptor string} + * + * @apiNote + * A symbolic descriptor for the type of the local variable is available + * through {@link #typeSymbol() typeSymbol()}. */ Utf8Entry type(); @@ -84,6 +116,7 @@ default ClassDesc typeSymbol() { /** * {@return a local variable pseudo-instruction} + * {@code slot} must be within {@code [0, 65535]}. * * @param slot the local variable slot * @param nameEntry the local variable name @@ -99,6 +132,7 @@ static LocalVariable of(int slot, Utf8Entry nameEntry, Utf8Entry descriptorEntry /** * {@return a local variable pseudo-instruction} + * {@code slot} must be within {@code [0, 65535]}. * * @param slot the local variable slot * @param name the local variable name diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/LocalVariableType.java b/src/java.base/share/classes/java/lang/classfile/instruction/LocalVariableType.java index c9427491733..1e28804a837 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/LocalVariableType.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/LocalVariableType.java @@ -24,12 +24,8 @@ */ package java.lang.classfile.instruction; -import java.lang.classfile.ClassFile; -import java.lang.classfile.CodeElement; -import java.lang.classfile.CodeModel; -import java.lang.classfile.Label; -import java.lang.classfile.PseudoInstruction; -import java.lang.classfile.Signature; +import java.lang.classfile.*; +import java.lang.classfile.attribute.LocalVariableTypeInfo; import java.lang.classfile.attribute.LocalVariableTypeTableAttribute; import java.lang.classfile.constantpool.Utf8Entry; @@ -39,16 +35,44 @@ /** * A pseudo-instruction which models a single entry in the {@link - * LocalVariableTypeTableAttribute}. Delivered as a {@link CodeElement} during - * traversal of the elements of a {@link CodeModel}, according to the setting of - * the {@link ClassFile.DebugElementsOption} option. + * LocalVariableTypeTableAttribute LocalVariableTypeTable} attribute. Delivered + * as a {@link CodeElement} during traversal of the elements of a {@link CodeModel}, + * according to the setting of the {@link ClassFile.DebugElementsOption} option. + *

+ * A local variable type entry is composite: + * {@snippet lang=text : + * // @link substring="LocalVariableType" target="#of(int, String, Signature, Label, Label)" : + * LocalVariableType( + * int slot, // @link substring="slot" target="#slot" + * String name, // @link substring="name" target="#name" + * Signature signature, // @link substring="signature" target="#signatureSymbol" + * Label startScope, // @link substring="startScope" target="#startScope" + * Label endScope // @link substring="endScope" target="#endScope" + * ) + * } + * Where {@code slot} is within {@code [0, 65535]}. + *

+ * Another model, {@link LocalVariableTypeInfo}, also models a local variable + * type entry; it has no dependency on a {@code CodeModel} and represents of bci + * values as {@code int}s instead of {@code Label}s, and is used as components + * of a {@link LocalVariableTypeTableAttribute}. * + * @apiNote + * {@code LocalVariableType} is used if a local variable has a parameterized + * type, a type argument, or an array type of one of the previous types as its + * type. A {@link LocalVariable} with the erased type should still be created + * for that local variable. + * + * @see LocalVariableTypeInfo + * @see CodeBuilder#localVariableType CodeBuilder::localVariableType + * @see ClassFile.DebugElementsOption * @since 24 */ public sealed interface LocalVariableType extends PseudoInstruction permits AbstractPseudoInstruction.UnboundLocalVariableType, BoundLocalVariableType { /** * {@return the local variable slot} + * The value is within {@code [0, 65535]}. */ int slot(); @@ -58,12 +82,16 @@ public sealed interface LocalVariableType extends PseudoInstruction Utf8Entry name(); /** - * {@return the local variable signature} + * {@return the local variable generic signature string} + * + * @apiNote + * A symbolic generic signature of the local variable is available + * through {@link #signatureSymbol() signatureSymbol()}. */ Utf8Entry signature(); /** - * {@return the local variable signature} + * {@return the local variable generic signature} */ default Signature signatureSymbol() { return Signature.parseFrom(signature().stringValue()); @@ -81,6 +109,7 @@ default Signature signatureSymbol() { /** * {@return a local variable type pseudo-instruction} + * {@code slot} must be within {@code [0, 65535]}. * * @param slot the local variable slot * @param nameEntry the local variable name @@ -96,6 +125,7 @@ static LocalVariableType of(int slot, Utf8Entry nameEntry, Utf8Entry signatureEn /** * {@return a local variable type pseudo-instruction} + * {@code slot} must be within {@code [0, 65535]}. * * @param slot the local variable slot * @param name the local variable name diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/LookupSwitchInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/LookupSwitchInstruction.java index 7b286e9cfd2..33e3ec002fd 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/LookupSwitchInstruction.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/LookupSwitchInstruction.java @@ -24,19 +24,36 @@ */ package java.lang.classfile.instruction; +import java.lang.classfile.CodeBuilder; import java.lang.classfile.CodeElement; import java.lang.classfile.CodeModel; import java.lang.classfile.Instruction; import java.lang.classfile.Label; +import java.lang.classfile.Opcode; import java.util.List; import jdk.internal.classfile.impl.AbstractInstruction; /** - * Models a {@code lookupswitch} instruction in the {@code code} array of a - * {@code Code} attribute. Delivered as a {@link CodeElement} when traversing - * the elements of a {@link CodeModel}. + * Models a {@link Opcode#LOOKUPSWITCH lookupswitch} instruction in the {@code + * code} array of a {@code Code} attribute. Delivered as a {@link CodeElement} + * when traversing the elements of a {@link CodeModel}. + *

+ * A lookup switch instruction is composite: + * {@snippet lang=text : + * // @link substring="LookupSwitchInstruction" target="#of" : + * LookupSwitchInstruction( + * Label defaultTarget, // @link substring="defaultTarget" target="#defaultTarget" + * List cases // @link substring="cases" target="#cases()" + * ) + * } + * If elements in {@code cases} are not sorted ascending by their {@link + * SwitchCase#caseValue caseValue}, a sorted version of the {@code cases} list + * will be written instead. * + * @see Opcode.Kind#LOOKUP_SWITCH + * @see CodeBuilder#lookupswitch CodeBuilder::lookupswitch + * @jvms 6.5.lookupswitch lookupswitch * @since 24 */ public sealed interface LookupSwitchInstruction extends Instruction diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/MonitorInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/MonitorInstruction.java index 1c8268cddd6..0efdfbdb34f 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/MonitorInstruction.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/MonitorInstruction.java @@ -24,6 +24,7 @@ */ package java.lang.classfile.instruction; +import java.lang.classfile.CodeBuilder; import java.lang.classfile.CodeElement; import java.lang.classfile.CodeModel; import java.lang.classfile.Instruction; @@ -33,9 +34,17 @@ import jdk.internal.classfile.impl.Util; /** - * Models a {@code monitorenter} or {@code monitorexit} instruction in the - * {@code code} array of a {@code Code} attribute. Delivered as a {@link - * CodeElement} when traversing the elements of a {@link CodeModel}. + * Models a {@link Opcode#MONITORENTER monitorenter} or {@link Opcode#MONITOREXIT + * monitorexit} instruction in the {@code code} array of a {@code Code} attribute. + * Corresponding opcodes have a {@linkplain Opcode#kind() kind} of {@link + * Opcode.Kind#MONITOR}. Delivered as a {@link CodeElement} when traversing the + * elements of a {@link CodeModel}. + *

+ * A monitor instruction is composite: + * {@snippet lang=text : + * // @link substring="MonitorInstruction" target="#of(Opcode)" : + * MonitorInstruction(Opcode opcode) // @link substring="opcode" target="#opcode" + * } * * @since 24 */ diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/NewMultiArrayInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/NewMultiArrayInstruction.java index 4a1f6cfd170..f7efd144422 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/NewMultiArrayInstruction.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/NewMultiArrayInstruction.java @@ -24,19 +24,34 @@ */ package java.lang.classfile.instruction; +import java.lang.classfile.CodeBuilder; import java.lang.classfile.CodeElement; import java.lang.classfile.CodeModel; import java.lang.classfile.Instruction; +import java.lang.classfile.Opcode; import java.lang.classfile.constantpool.ClassEntry; import jdk.internal.classfile.impl.AbstractInstruction; import jdk.internal.classfile.impl.BytecodeHelpers; /** - * Models a {@code multianewarray} invocation instruction in the {@code code} + * Models a {@link Opcode#MULTIANEWARRAY multianewarray} instruction in the {@code code} * array of a {@code Code} attribute. Delivered as a {@link CodeElement} * when traversing the elements of a {@link CodeModel}. + *

+ * A new multi-dimensional array instruction is composite: + * {@snippet lang=text : + * // @link substring="NewMultiArrayInstruction" target="#of" : + * NewMultiArrayInstruction( + * ClassEntry arrayType, // @link substring="arrayType" target="#arrayType" + * int dimensions // @link substring="dimensions" target="#dimensions" + * ) + * } + * where the {@code arrayType} is an array class. * + * @see Opcode.Kind#NEW_MULTI_ARRAY + * @see CodeBuilder#multianewarray CodeBuilder::multianewarray + * @jvms 6.5.multianewarray multianewarray * @since 24 */ public sealed interface NewMultiArrayInstruction extends Instruction @@ -44,7 +59,7 @@ public sealed interface NewMultiArrayInstruction extends Instruction AbstractInstruction.UnboundNewMultidimensionalArrayInstruction { /** - * {@return the type of the array, as a symbolic descriptor} + * {@return the type of the array} */ ClassEntry arrayType(); diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/NewObjectInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/NewObjectInstruction.java index f063733b64f..62b0233be87 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/NewObjectInstruction.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/NewObjectInstruction.java @@ -24,18 +24,30 @@ */ package java.lang.classfile.instruction; +import java.lang.classfile.CodeBuilder; import java.lang.classfile.CodeElement; import java.lang.classfile.CodeModel; import java.lang.classfile.Instruction; +import java.lang.classfile.Opcode; import java.lang.classfile.constantpool.ClassEntry; import jdk.internal.classfile.impl.AbstractInstruction; /** - * Models a {@code new} instruction in the {@code code} array of a {@code Code} + * Models a {@link Opcode#NEW new} instruction in the {@code code} array of a {@code Code} * attribute. Delivered as a {@link CodeElement} when traversing the elements * of a {@link CodeModel}. + *

+ * A new object instruction is composite: + * {@snippet lang=text : + * // @link substring="NewObjectInstruction" target="#of" : + * NewObjectInstruction(ClassEntry className) // @link substring="className" target="#className" + * } + * where the {@code className} is a non-abstract class. * + * @see Opcode.Kind#NEW_OBJECT + * @see CodeBuilder#new_ CodeBuilder::new_ + * @jvms 6.5.new new * @since 24 */ public sealed interface NewObjectInstruction extends Instruction diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/NewPrimitiveArrayInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/NewPrimitiveArrayInstruction.java index 411bf7f6b55..c1e2c9d12fa 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/NewPrimitiveArrayInstruction.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/NewPrimitiveArrayInstruction.java @@ -24,18 +24,30 @@ */ package java.lang.classfile.instruction; +import java.lang.classfile.CodeBuilder; import java.lang.classfile.CodeElement; import java.lang.classfile.CodeModel; import java.lang.classfile.Instruction; +import java.lang.classfile.Opcode; import java.lang.classfile.TypeKind; import jdk.internal.classfile.impl.AbstractInstruction; /** - * Models a {@code newarray} invocation instruction in the {@code code} + * Models a {@link Opcode#NEWARRAY newarray} instruction in the {@code code} * array of a {@code Code} attribute. Delivered as a {@link CodeElement} * when traversing the elements of a {@link CodeModel}. + *

+ * A new primitive array instruction is composite: + * {@snippet lang=text : + * // @link substring="NewPrimitiveArrayInstruction" target="#of" : + * NewPrimitiveArrayInstruction(TypeKind typeKind) // @link substring="typeKind" target="#typeKind" + * } + * where {@code typeKind} is primitive and not {@code void}. * + * @see Opcode.Kind#NEW_PRIMITIVE_ARRAY + * @see CodeBuilder#newarray CodeBuilder::newarray + * @jvms 6.5.newarray newarray * @since 24 */ public sealed interface NewPrimitiveArrayInstruction extends Instruction @@ -43,6 +55,10 @@ public sealed interface NewPrimitiveArrayInstruction extends Instruction AbstractInstruction.UnboundNewPrimitiveArrayInstruction { /** * {@return the component type of the array} + * + * @apiNote + * The backing array code for this instruction is available through + * {@link TypeKind#newarrayCode() typeKind().newarrayCode()}. */ TypeKind typeKind(); @@ -50,8 +66,9 @@ public sealed interface NewPrimitiveArrayInstruction extends Instruction * {@return a new primitive array instruction} * * @param typeKind the component type of the array - * @throws IllegalArgumentException when the {@code typeKind} is not a legal - * primitive array component type + * @throws IllegalArgumentException when {@code typeKind} is not primitive + * or is {@code void} + * @see TypeKind#fromNewarrayCode(int) TypeKind::fromNewarrayCode */ static NewPrimitiveArrayInstruction of(TypeKind typeKind) { // Implicit null-check: diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/NewReferenceArrayInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/NewReferenceArrayInstruction.java index c85ed9dd3d9..a092c068a36 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/NewReferenceArrayInstruction.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/NewReferenceArrayInstruction.java @@ -24,18 +24,29 @@ */ package java.lang.classfile.instruction; +import java.lang.classfile.CodeBuilder; import java.lang.classfile.CodeElement; import java.lang.classfile.CodeModel; import java.lang.classfile.Instruction; +import java.lang.classfile.Opcode; import java.lang.classfile.constantpool.ClassEntry; import jdk.internal.classfile.impl.AbstractInstruction; /** - * Models a {@code anewarray} invocation instruction in the {@code code} + * Models a {@link Opcode#ANEWARRAY anewarray} instruction in the {@code code} * array of a {@code Code} attribute. Delivered as a {@link CodeElement} * when traversing the elements of a {@link CodeModel}. + *

+ * A new reference array instruction is composite: + * {@snippet lang=text : + * // @link substring="NewReferenceArrayInstruction" target="#of" : + * NewReferenceArrayInstruction(ClassEntry componentType) // @link substring="componentType" target="#componentType" + * } * + * @see Opcode.Kind#NEW_REF_ARRAY + * @see CodeBuilder#newarray CodeBuilder::anewarray + * @jvms 6.5.anewarray anewarray * @since 24 */ public sealed interface NewReferenceArrayInstruction extends Instruction diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/NopInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/NopInstruction.java index 3c11803109a..cf0b9f25ac9 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/NopInstruction.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/NopInstruction.java @@ -24,17 +24,23 @@ */ package java.lang.classfile.instruction; +import java.lang.classfile.CodeBuilder; import java.lang.classfile.CodeElement; import java.lang.classfile.CodeModel; import java.lang.classfile.Instruction; +import java.lang.classfile.Opcode; import jdk.internal.classfile.impl.AbstractInstruction; /** - * Models a {@code nop} invocation instruction in the {@code code} + * Models a {@link Opcode#NOP nop} instruction in the {@code code} * array of a {@code Code} attribute. Delivered as a {@link CodeElement} * when traversing the elements of a {@link CodeModel}. + *

+ * A no-op instruction has no visible state. * + * @see CodeBuilder#nop CodeBuilder::nop + * @jvms 6.5.nop nop * @since 24 */ public sealed interface NopInstruction extends Instruction diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/OperatorInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/OperatorInstruction.java index d1eb8aa1a3d..b4daf55e3a5 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/OperatorInstruction.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/OperatorInstruction.java @@ -35,23 +35,31 @@ /** * Models an arithmetic operator instruction in the {@code code} array of a - * {@code Code} attribute. Corresponding opcodes will have a {@code kind} of + * {@code Code} attribute. Corresponding opcodes have a {@linkplain Opcode#kind() kind} of * {@link Opcode.Kind#OPERATOR}. Delivered as a {@link CodeElement} when * traversing the elements of a {@link CodeModel}. + *

+ * An operator instruction is composite: + * {@snippet lang=text : + * // @link substring="OperatorInstruction" target="#of" : + * OperatorInstruction(Opcode opcode) // @link substring="opcode" target="#opcode()" + * } * + * @see Opcode.Kind#OPERATOR * @since 24 */ public sealed interface OperatorInstruction extends Instruction permits AbstractInstruction.UnboundOperatorInstruction { /** * {@return the operand type of the instruction} + * This is derived from the {@link #opcode opcode}. */ TypeKind typeKind(); /** * {@return an operator instruction} * - * @param op the opcode for the specific type of array load instruction, + * @param op the opcode for the specific type of operator instruction, * which must be of kind {@link Opcode.Kind#OPERATOR} * @throws IllegalArgumentException if the opcode kind is not * {@link Opcode.Kind#OPERATOR}. diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/ReturnInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/ReturnInstruction.java index 3bbb96b1cbe..aca9196eabf 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/ReturnInstruction.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/ReturnInstruction.java @@ -24,6 +24,7 @@ */ package java.lang.classfile.instruction; +import java.lang.classfile.CodeBuilder; import java.lang.classfile.CodeElement; import java.lang.classfile.CodeModel; import java.lang.classfile.Instruction; @@ -36,22 +37,35 @@ /** * Models a return-from-method instruction in the {@code code} array of a - * {@code Code} attribute. Corresponding opcodes will have a {@code kind} of + * {@code Code} attribute. Corresponding opcodes have a {@linkplain Opcode#kind() kind} of * {@link Opcode.Kind#RETURN}. Delivered as a {@link CodeElement} when * traversing the elements of a {@link CodeModel}. + *

+ * A return-from-method instruction is composite: + * {@snippet lang=text : + * // @link substring="ReturnInstruction" target="#of(TypeKind)" : + * ReturnInstruction(TypeKind typeKind) // @link substring="typeKind" target="#typeKind()" + * } + * where {@code typeKind} is {@linkplain TypeKind##computational-type + * computational} or {@link TypeKind#VOID void}. * + * @see Opcode.Kind#RETURN + * @see CodeBuilder#return_(TypeKind) CodeBuilder::return_ * @since 24 */ public sealed interface ReturnInstruction extends Instruction permits AbstractInstruction.UnboundReturnInstruction { /** - * {@return the type of the return instruction} + * {@return the {@linkplain TypeKind##computational-type computational type}, including + * {@link TypeKind#VOID void}, of the return instruction} */ TypeKind typeKind(); /** * {@return a return instruction} + * {@code typeKind} is {@linkplain TypeKind#asLoadable() converted} to its + * computational type. * * @param typeKind the type of the return instruction */ diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/StackInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/StackInstruction.java index b01b206e368..8ef413937bc 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/StackInstruction.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/StackInstruction.java @@ -34,10 +34,17 @@ /** * Models a stack manipulation instruction in the {@code code} array of a - * {@code Code} attribute. Corresponding opcodes will have a {@code kind} of + * {@code Code} attribute. Corresponding opcodes have a {@linkplain Opcode#kind() kind} of * {@link Opcode.Kind#STACK}. Delivered as a {@link CodeElement} when * traversing the elements of a {@link CodeModel}. + *

+ * A stack manipulation instruction is composite: + * {@snippet lang=text : + * // @link substring="StackInstruction" target="#of" : + * StackInstruction(Opcode opcode) // @link substring="opcode" target="#opcode()" + * } * + * @see Opcode.Kind#STACK * @since 24 */ public sealed interface StackInstruction extends Instruction diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/StoreInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/StoreInstruction.java index 1d7bdce1fdf..93d33e0b7c2 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/StoreInstruction.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/StoreInstruction.java @@ -24,6 +24,7 @@ */ package java.lang.classfile.instruction; +import java.lang.classfile.CodeBuilder; import java.lang.classfile.CodeElement; import java.lang.classfile.CodeModel; import java.lang.classfile.Instruction; @@ -36,10 +37,28 @@ /** * Models a local variable store instruction in the {@code code} array of a - * {@code Code} attribute. Corresponding opcodes will have a {@code kind} of + * {@code Code} attribute. Corresponding opcodes have a {@linkplain Opcode#kind() kind} of * {@link Opcode.Kind#STORE}. Delivered as a {@link CodeElement} when * traversing the elements of a {@link CodeModel}. + *

+ * A local variable store instruction is composite: + * {@snippet lang=text : + * // @link substring="StoreInstruction" target="#of(TypeKind, int)" : + * StoreInstruction( + * TypeKind typeKind, // @link substring="typeKind" target="#typeKind" + * int slot // @link substring="slot" target="#slot" + * ) + * } + * where {@code TypeKind} is {@linkplain TypeKind##computational-type + * computational}, and {@code slot} is within {@code [0, 65535]}. + *

+ * {@code astore} series of instructions, or {@code reference} type store + * instructions, can also operate on the {@link TypeKind##returnAddress + * returnAddress} type from discontinued {@linkplain + * DiscontinuedInstruction.JsrInstruction jump subroutine instructions}. * + * @see Opcode.Kind#STORE + * @see CodeBuilder#storeLocal CodeBuilder::storeLocal * @since 24 */ public sealed interface StoreInstruction extends Instruction @@ -47,16 +66,23 @@ public sealed interface StoreInstruction extends Instruction /** * {@return the local variable slot to store to} + * The value is within {@code [0, 65535]}. */ int slot(); /** - * {@return the type of the value to be stored} + * {@return the {@linkplain TypeKind##computational-type computational type} + * of the value to be stored} The {@link TypeKind#REFERENCE reference} + * type store instructions also operate on the {@code returnAddress} type, + * which does not apply to {@code reference} type load instructions. */ TypeKind typeKind(); /** * {@return a local variable store instruction} + * {@code kind} is {@linkplain TypeKind#asLoadable() converted} to its + * computational type. + * {@code slot} must be within {@code [0, 65535]}. * * @param kind the type of the value to be stored * @param slot the local variable slot to store to @@ -70,6 +96,20 @@ static StoreInstruction of(TypeKind kind, int slot) { /** * {@return a local variable store instruction} + *

+ * The range of {@code slot} is restricted by the {@code op} and its + * {@linkplain Opcode#sizeIfFixed() size}: + *

    + *
  • If {@code op} has size 1, {@code slot} must be exactly the slot value + * implied by the opcode. + *
  • If {@code op} has size 2, {@code slot} must be within {@code [0, 255]}. + *
  • If {@code op} has size 4, {@code slot} must be within {@code [0, 65535]}. + *
+ * + * @apiNote + * The explicit {@code op} argument allows creating {@code wide} or + * regular store instructions when the {@code slot} can be encoded + * with more optimized store instructions. * * @param op the opcode for the specific type of store instruction, * which must be of kind {@link Opcode.Kind#STORE} diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/SwitchCase.java b/src/java.base/share/classes/java/lang/classfile/instruction/SwitchCase.java index 3f5f91031b6..cce8f8ef03a 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/SwitchCase.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/SwitchCase.java @@ -29,12 +29,20 @@ import jdk.internal.classfile.impl.AbstractInstruction; /** - * Models a single case in a {@code lookupswitch} or {@code tableswitch} - * instruction. + * Models a single case in a {@link LookupSwitchInstruction lookupswitch} or + * {@link TableSwitchInstruction tableswitch} instruction. + *

+ * A switch case is composite: + * {@snippet lang=text : + * // @link substring="SwitchCase" target="#of" : + * SwitchCase( + * int caseValue, // @link substring="caseValue" target="#caseValue" + * Label target // @link substring="target" target="#target" + * ) + * } * * @see LookupSwitchInstruction * @see TableSwitchInstruction - * * @since 24 */ public sealed interface SwitchCase @@ -47,11 +55,10 @@ public sealed interface SwitchCase Label target(); /** - * Create a {@linkplain SwitchCase} + * {@return a new switch case} * * @param caseValue the integer value for the case * @param target the branch target for the case - * @return the {@linkplain SwitchCase} */ static SwitchCase of(int caseValue, Label target) { return new AbstractInstruction.SwitchCaseImpl(caseValue, target); diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/TableSwitchInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/TableSwitchInstruction.java index bbe7a4d6c0c..3f7245fad49 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/TableSwitchInstruction.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/TableSwitchInstruction.java @@ -24,19 +24,45 @@ */ package java.lang.classfile.instruction; +import java.lang.classfile.CodeBuilder; import java.lang.classfile.CodeElement; import java.lang.classfile.CodeModel; import java.lang.classfile.Instruction; import java.lang.classfile.Label; +import java.lang.classfile.Opcode; import java.util.List; import jdk.internal.classfile.impl.AbstractInstruction; /** - * Models a {@code tableswitch} instruction in the {@code code} array of a + * Models a {@link Opcode#TABLESWITCH tableswitch} instruction in the {@code code} array of a * {@code Code} attribute. Delivered as a {@link CodeElement} when traversing * the elements of a {@link CodeModel}. + *

+ * A table switch instruction is composite: + * {@snippet lang=text : + * // @link substring="TableSwitchInstruction" target="#of" : + * TableSwitchInstruction( + * int lowValue, // @link substring="int lowValue" target="#lowValue" + * int highValue, // @link substring="int highValue" target="#highValue" + * Label defaultTarget, // @link substring="defaultTarget" target="#defaultTarget" + * List cases // @link substring="cases" target="#cases()" + * ) + * } + *

+ * When read from {@code class} files, the {@code cases} may omit cases that + * duplicate the default target. The list is sorted ascending by the {@link + * SwitchCase#caseValue() caseValue}. + *

+ * When writing to {@code class} file, the order in the {@code cases} list does + * not matter, as there is only one valid order in the physical representation + * of table switch entries. Treatment of elements in {@code cases} whose value + * is less than {@code lowValue} or greater than {@code highValue}, and elements + * whose value duplicates that of another, is not specified. * + * @see Opcode.Kind#TABLE_SWITCH + * @see CodeBuilder#tableswitch CodeBuilder::tableswitch + * @jvms 6.5.tableswitch tableswitch * @since 24 */ public sealed interface TableSwitchInstruction extends Instruction @@ -67,7 +93,8 @@ public sealed interface TableSwitchInstruction extends Instruction * @param lowValue the low value of the switch target range, inclusive * @param highValue the high value of the switch target range, inclusive * @param defaultTarget the default target of the switch - * @param cases the cases of the switch + * @param cases the cases of the switch; duplicate or out of bound case + * handling is not specified */ static TableSwitchInstruction of(int lowValue, int highValue, Label defaultTarget, List cases) { return new AbstractInstruction.UnboundTableSwitchInstruction(lowValue, highValue, defaultTarget, cases); diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/ThrowInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/ThrowInstruction.java index ec6fdc38626..4504b855c4c 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/ThrowInstruction.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/ThrowInstruction.java @@ -24,17 +24,23 @@ */ package java.lang.classfile.instruction; +import java.lang.classfile.CodeBuilder; import java.lang.classfile.CodeElement; import java.lang.classfile.CodeModel; import java.lang.classfile.Instruction; +import java.lang.classfile.Opcode; import jdk.internal.classfile.impl.AbstractInstruction; /** - * Models an {@code athrow} instruction in the {@code code} array of a + * Models an {@link Opcode#ATHROW athrow} instruction in the {@code code} array of a * {@code Code} attribute. Delivered as a {@link CodeElement} when traversing * the elements of a {@link CodeModel}. + *

+ * A throw instruction has no visible state. * + * @see Opcode.Kind#THROW_EXCEPTION + * @see CodeBuilder#athrow CodeBuiler::athrow * @since 24 */ public sealed interface ThrowInstruction extends Instruction diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/TypeCheckInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/TypeCheckInstruction.java index 032e7a8462b..3091cf05e71 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/TypeCheckInstruction.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/TypeCheckInstruction.java @@ -36,9 +36,24 @@ import jdk.internal.classfile.impl.Util; /** - * Models an {@code instanceof} or {@code checkcast} instruction in the {@code - * code} array of a {@code Code} attribute. Delivered as a {@link CodeElement} - * when traversing the elements of a {@link CodeModel}. + * Models an {@link Opcode#INSTANCEOF instanceof} or a {@link Opcode#CHECKCAST checkcast} + * instruction in the {@code code} array of a {@code Code} attribute. Corresponding + * opcodes have a {@linkplain Opcode#kind() kind} of {@link Opcode.Kind#TYPE_CHECK}. + * Delivered as a {@link CodeElement} when traversing the elements of a {@link CodeModel}. + *

+ * An {@code instanceof} checks the type and pushes an integer to the operand stack. + * A {@code checkcast} checks the type and throws a {@link ClassCastException} if + * the check fails. {@code instanceof} treat the {@code null} reference as a + * failure, while {@code checkcast} treat the {@code null} reference as a success. + *

+ * A type check instruction is composite: + * {@snippet lang=text : + * // @link substring="TypeCheckInstruction" target="#of(Opcode, ClassEntry)" : + * TypeCheckInstruction( + * Opcode opcode, // @link substring="opcode" target="#opcode" + * ClassEntry type // @link substring="type" target="#type" + * ) + * } * * @since 24 */ @@ -47,7 +62,7 @@ public sealed interface TypeCheckInstruction extends Instruction AbstractInstruction.UnboundTypeCheckInstruction { /** - * {@return the type against which the instruction checks or casts} + * {@return the type against which the instruction checks} */ ClassEntry type(); @@ -58,7 +73,7 @@ public sealed interface TypeCheckInstruction extends Instruction * which must be of kind {@link Opcode.Kind#TYPE_CHECK} * @param type the type against which to check or cast * @throws IllegalArgumentException if the opcode kind is not - * {@link Opcode.Kind#TYPE_CHECK}. + * {@link Opcode.Kind#TYPE_CHECK} */ static TypeCheckInstruction of(Opcode op, ClassEntry type) { Util.checkKind(op, Opcode.Kind.TYPE_CHECK); @@ -71,6 +86,8 @@ static TypeCheckInstruction of(Opcode op, ClassEntry type) { * @param op the opcode for the specific type of type check instruction, * which must be of kind {@link Opcode.Kind#TYPE_CHECK} * @param type the type against which to check or cast + * @throws IllegalArgumentException if the opcode kind is not + * {@link Opcode.Kind#TYPE_CHECK}, or if {@code type} is primitive */ static TypeCheckInstruction of(Opcode op, ClassDesc type) { return of(op, TemporaryConstantPool.INSTANCE.classEntry(type)); diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/package-info.java b/src/java.base/share/classes/java/lang/classfile/instruction/package-info.java index d2a36e16615..e732aadf1ec 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/package-info.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/package-info.java @@ -26,9 +26,45 @@ /** *

Provides interfaces describing code instructions for the {@link java.lang.classfile} library.

* - * The {@code java.lang.classfile.attribute} package contains interfaces describing code instructions. + * The {@code java.lang.classfile.instruction} package contains interfaces describing code instructions. + * Implementations of these interfaces are immutable. + *

+ * Unless otherwise specified, passing {@code null} or an array or collection containing a {@code null} element as an + * argument to a constructor or method of any Class-File API class or interface will cause a {@link NullPointerException} + * to be thrown. * + *

Reading of instructions

+ * Instructions and pseudo-instructions are usually accessed from a {@link CodeModel}, such as {@link CodeModel#forEach + * CodeModel::forEach}, and categorized by pattern-matching. + *

+ * When read from {@code class} files, instructions are lazily inflated; the contents of these instructions, besides the + * bare structure, are not evaluated to speed up parsing. Instructions to users interest, such as those filtered by the + * pattern matching, have their contents read on demand, to avoid unnecessary reading of unrelated instructions in a code + * array. + *

+ * Due to the lazy nature of {@code class} file parsing, {@link IllegalArgumentException} indicating malformed + * {@code class} file data can be thrown at any method invocation. For example, an instruction object for a {@link + * TypeCheckInstruction} may be obtained from a {@code CodeModel}, but the subsequent invocation of {@link + * TypeCheckInstruction#type() .type()} may fail with {@code IllegalArgumentException} because the instruction refers + * to a bad constant pool index. + * + *

Writing of instructions

+ * Writing of instructions happen on {@link CodeBuilder}. The most basic way to write instructions is to pass an + * instruction object to {@link CodeBuilder#with CodeBuilder::with}, which supports all valid instructions. + * Yet, {@code CodeBuilder} provides a lot of {@linkplain CodeBuilder##instruction-factories convenience factory methods} + * for easy creation of instructions, named by their mnemonic. These accessors are more concise, and often more + * efficient at run-time than passing instruction objects. + *

+ * Due to restrictions in the {@code class} file format, some instructions may not be representable in a {@code CodeBuilder}. + * In some scenarios, such as for {@link BranchInstruction}, Class-File API options control if alternatives can be used + * in code generation instead. Otherwise, they can be configured to fail-fast to ensure the parity of {@code CodeBuilder} + * commands with the generated {@code code} array data. + * + * @jvms 6.5 Instructions * @since 24 */ package java.lang.classfile.instruction; +import java.lang.classfile.CodeBuilder; +import java.lang.classfile.CodeModel; + diff --git a/src/java.base/share/classes/java/math/BigDecimal.java b/src/java.base/share/classes/java/math/BigDecimal.java index abd49aa69bc..ceb9053fc2c 100644 --- a/src/java.base/share/classes/java/math/BigDecimal.java +++ b/src/java.base/share/classes/java/math/BigDecimal.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -313,13 +313,13 @@ * time or space of operations can screen out {@code BigDecimal} * values with unscaled values or scales above a chosen magnitude. * - * @see BigInteger - * @see MathContext - * @see RoundingMode - * @see java.util.SortedMap - * @see java.util.SortedSet - * @see - * IEEE Standard for Floating-Point Arithmetic + * @see BigInteger + * @see MathContext + * @see RoundingMode + * @see java.util.SortedMap + * @see java.util.SortedSet + * @spec https://standards.ieee.org/ieee/754/6210/ + * IEEE Standard for Floating-Point Arithmetic * * @author Josh Bloch * @author Mike Cowlishaw diff --git a/src/java.base/share/classes/java/math/MathContext.java b/src/java.base/share/classes/java/math/MathContext.java index 25d01c9af4c..d0c1cb4a5a9 100644 --- a/src/java.base/share/classes/java/math/MathContext.java +++ b/src/java.base/share/classes/java/math/MathContext.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -46,10 +46,10 @@ * used for rounding. * * - * @see BigDecimal - * @see RoundingMode - * @see - * IEEE Standard for Floating-Point Arithmetic + * @see BigDecimal + * @see RoundingMode + * @spec https://standards.ieee.org/ieee/754/6210/ + * IEEE Standard for Floating-Point Arithmetic * * @author Mike Cowlishaw * @author Joseph D. Darcy diff --git a/src/java.base/share/classes/java/math/RoundingMode.java b/src/java.base/share/classes/java/math/RoundingMode.java index 361c19d7f18..e66a64e143f 100644 --- a/src/java.base/share/classes/java/math/RoundingMode.java +++ b/src/java.base/share/classes/java/math/RoundingMode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -109,10 +109,10 @@ * this correspondence will be noted in the documentation of the * particular constant. * - * @see BigDecimal - * @see MathContext - * @see - * IEEE Standard for Floating-Point Arithmetic + * @see BigDecimal + * @see MathContext + * @spec https://standards.ieee.org/ieee/754/6210/ + * IEEE Standard for Floating-Point Arithmetic * @jls 15.4 Floating-point Expressions * * @author Josh Bloch diff --git a/src/java.base/share/classes/java/net/Socket.java b/src/java.base/share/classes/java/net/Socket.java index 929e99b5303..8566367a62d 100644 --- a/src/java.base/share/classes/java/net/Socket.java +++ b/src/java.base/share/classes/java/net/Socket.java @@ -569,9 +569,8 @@ void setConnected() { /** * Connects this socket to the server. * - *

If the endpoint is an unresolved {@link InetSocketAddress}, or the - * connection cannot be established, then the socket is closed, and an - * {@link IOException} is thrown. + *

If the connection cannot be established, then the socket is closed, + * and an {@link IOException} is thrown. * *

This method is {@linkplain Thread#interrupt() interruptible} in the * following circumstances: @@ -591,8 +590,8 @@ void setConnected() { * @param endpoint the {@code SocketAddress} * @throws IOException if an error occurs during the connection, the socket * is already connected or the socket is closed - * @throws UnknownHostException if the endpoint is an unresolved - * {@link InetSocketAddress} + * @throws UnknownHostException if the connection could not be established + * because the endpoint is an unresolved {@link InetSocketAddress} * @throws java.nio.channels.IllegalBlockingModeException * if this socket has an associated channel, * and the channel is in non-blocking mode @@ -609,9 +608,8 @@ public void connect(SocketAddress endpoint) throws IOException { * A timeout of zero is interpreted as an infinite timeout. The connection * will then block until established or an error occurs. * - *

If the endpoint is an unresolved {@link InetSocketAddress}, the - * connection cannot be established, or the timeout expires before the - * connection is established, then the socket is closed, and an + *

If the connection cannot be established, or the timeout expires + * before the connection is established, then the socket is closed, and an * {@link IOException} is thrown. * *

This method is {@linkplain Thread#interrupt() interruptible} in the @@ -634,8 +632,8 @@ public void connect(SocketAddress endpoint) throws IOException { * @throws IOException if an error occurs during the connection, the socket * is already connected or the socket is closed * @throws SocketTimeoutException if timeout expires before connecting - * @throws UnknownHostException if the endpoint is an unresolved - * {@link InetSocketAddress} + * @throws UnknownHostException if the connection could not be established + * because the endpoint is an unresolved {@link InetSocketAddress} * @throws java.nio.channels.IllegalBlockingModeException * if this socket has an associated channel, * and the channel is in non-blocking mode @@ -660,12 +658,6 @@ public void connect(SocketAddress endpoint, int timeout) throws IOException { if (!(endpoint instanceof InetSocketAddress epoint)) throw new IllegalArgumentException("Unsupported address type"); - if (epoint.isUnresolved()) { - var uhe = new UnknownHostException(epoint.getHostName()); - closeSuppressingExceptions(uhe); - throw uhe; - } - InetAddress addr = epoint.getAddress(); checkAddress(addr, "connect"); diff --git a/src/java.base/share/classes/java/util/ResourceBundle.java b/src/java.base/share/classes/java/util/ResourceBundle.java index 989cc09f388..4206dda6a3a 100644 --- a/src/java.base/share/classes/java/util/ResourceBundle.java +++ b/src/java.base/share/classes/java/util/ResourceBundle.java @@ -3654,8 +3654,7 @@ private static String toPackageName(String bundleName) { } - private static final boolean TRACE_ON = Boolean.getBoolean( - System.getProperty("resource.bundle.debug", "false")); + private static final boolean TRACE_ON = Boolean.getBoolean("resource.bundle.debug"); private static void trace(String format, Object... params) { if (TRACE_ON) diff --git a/src/java.base/share/classes/java/util/stream/Gatherers.java b/src/java.base/share/classes/java/util/stream/Gatherers.java index b394f6fc7d8..0a98d7d5033 100644 --- a/src/java.base/share/classes/java/util/stream/Gatherers.java +++ b/src/java.base/share/classes/java/util/stream/Gatherers.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,7 @@ import java.util.ArrayDeque; import java.util.List; import java.util.Objects; +import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.FutureTask; @@ -350,86 +351,103 @@ public static Gatherer mapConcurrent( final int maxConcurrency, final Function mapper) { if (maxConcurrency < 1) - throw new IllegalArgumentException( - "'maxConcurrency' must be greater than 0"); + throw new IllegalArgumentException("'maxConcurrency' must be greater than 0"); Objects.requireNonNull(mapper, "'mapper' must not be null"); - class State { - // ArrayDeque default initial size is 16 - final ArrayDeque> window = - new ArrayDeque<>(Math.min(maxConcurrency, 16)); - final Semaphore windowLock = new Semaphore(maxConcurrency); - - final boolean integrate(T element, - Downstream downstream) { - if (!downstream.isRejecting()) - createTaskFor(element); - return flush(0, downstream); + final class MapConcurrentTask extends FutureTask { + final Thread thread; + private MapConcurrentTask(Callable callable) { + super(callable); + this.thread = Thread.ofVirtual().unstarted(this); } + } - final void createTaskFor(T element) { - windowLock.acquireUninterruptibly(); + final class State { + private final ArrayDeque wip = + new ArrayDeque<>(Math.min(maxConcurrency, 16)); - var task = new FutureTask(() -> { - try { - return mapper.apply(element); - } finally { - windowLock.release(); - } - }); + boolean integrate(T element, Downstream downstream) { + // Prepare the next task and add it to the work-in-progress + final var task = new MapConcurrentTask(() -> mapper.apply(element)); + wip.addLast(task); + + assert wip.peekLast() == task; + assert wip.size() <= maxConcurrency; - var wasAddedToWindow = window.add(task); - assert wasAddedToWindow; + // Start the next task + task.thread.start(); - Thread.startVirtualThread(task); + // Flush at least 1 element if we're at capacity + return flush(wip.size() < maxConcurrency ? 0 : 1, downstream); } - final boolean flush(long atLeastN, - Downstream downstream) { - boolean proceed = !downstream.isRejecting(); - boolean interrupted = false; + boolean flush(long atLeastN, Downstream downstream) { + boolean success = false, interrupted = false; try { - Future current; - while (proceed - && (current = window.peek()) != null - && (current.isDone() || atLeastN > 0)) { - proceed &= downstream.push(current.get()); + boolean proceed = !downstream.isRejecting(); + MapConcurrentTask current; + while ( + proceed + && (current = wip.peekFirst()) != null + && (current.isDone() || atLeastN > 0) + ) { + R result; + + // Ensure that the task is done before proceeding + for (;;) { + try { + result = current.get(); + break; + } catch (InterruptedException ie) { + interrupted = true; // ignore for now, and restore later + } + } + + proceed &= downstream.push(result); atLeastN -= 1; - var correctRemoval = window.pop() == current; + final var correctRemoval = wip.pollFirst() == current; assert correctRemoval; } - } catch(InterruptedException ie) { - proceed = false; - interrupted = true; + return (success = proceed); // Ensure that cleanup occurs if needed } catch (ExecutionException e) { - proceed = false; // Ensure cleanup final var cause = e.getCause(); throw (cause instanceof RuntimeException re) ? re : new RuntimeException(cause == null ? e : cause); } finally { - // Clean up - if (!proceed) { - Future next; - while ((next = window.pollFirst()) != null) { - next.cancel(true); + // Clean up work-in-progress + if (!success && !wip.isEmpty()) { + // First signal cancellation for all tasks in progress + for (var task : wip) + task.cancel(true); + + // Then wait for all in progress task Threads to exit + MapConcurrentTask next; + while ((next = wip.pollFirst()) != null) { + while (next.thread.isAlive()) { + try { + next.thread.join(); + } catch (InterruptedException ie) { + interrupted = true; // ignore, for now, and restore later + } + } } } - } - - if (interrupted) - Thread.currentThread().interrupt(); - return proceed; + // integrate(..) could be called from different threads each time + // so we need to restore the interrupt on the calling thread + if (interrupted) + Thread.currentThread().interrupt(); + } } } return Gatherer.ofSequential( - State::new, - Integrator.ofGreedy(State::integrate), - (state, downstream) -> state.flush(Long.MAX_VALUE, downstream) + State::new, + Integrator.ofGreedy(State::integrate), + (state, downstream) -> state.flush(Long.MAX_VALUE, downstream) ); } diff --git a/src/java.base/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java b/src/java.base/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java index a52881b047b..f767588193f 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java +++ b/src/java.base/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java @@ -145,12 +145,17 @@ private NativeMemorySegmentImpl reinterpretInternal(Class callerClass, long n Reflection.ensureNativeAccess(callerClass, MemorySegment.class, "reinterpret", false); Utils.checkNonNegativeArgument(newSize, "newSize"); if (!isNative()) throw new UnsupportedOperationException("Not a native segment"); - Runnable action = cleanup != null ? - () -> cleanup.accept(SegmentFactories.makeNativeSegmentUnchecked(address(), newSize)) : - null; + Runnable action = cleanupAction(address(), newSize, cleanup); return SegmentFactories.makeNativeSegmentUnchecked(address(), newSize, scope, readOnly, action); } + // Using a static helper method ensures there is no unintended lambda capturing of `this` + private static Runnable cleanupAction(long address, long newSize, Consumer cleanup) { + return cleanup != null ? + () -> cleanup.accept(SegmentFactories.makeNativeSegmentUnchecked(address, newSize)) : + null; + } + private AbstractMemorySegmentImpl asSliceNoCheck(long offset, long newSize) { return dup(offset, newSize, readOnly, scope); } diff --git a/src/java.base/share/classes/module-info.java b/src/java.base/share/classes/module-info.java index 3c293770003..5b0117a1efc 100644 --- a/src/java.base/share/classes/module-info.java +++ b/src/java.base/share/classes/module-info.java @@ -155,7 +155,6 @@ exports jdk.internal.javac to java.compiler, java.desktop, // for ScopedValue - java.se, // for ParticipatesInPreview jdk.compiler, jdk.incubator.vector, // participates in preview features jdk.jartool, // participates in preview features diff --git a/src/java.base/share/classes/sun/launcher/resources/launcher_de.properties b/src/java.base/share/classes/sun/launcher/resources/launcher_de.properties index 12ab942f91f..1f922b4cf73 100644 --- a/src/java.base/share/classes/sun/launcher/resources/launcher_de.properties +++ b/src/java.base/share/classes/sun/launcher/resources/launcher_de.properties @@ -24,22 +24,25 @@ # # Translators please note do not translate the options themselves -java.launcher.opt.header = Verwendung: {0} [Optionen] [args...]\n (zur Ausführung einer Klasse)\n oder {0} [Optionen] -jar [args...]\n (zur Ausführung einer JAR-Datei)\n oder {0} [Optionen] -m [/] [args...]\n {0} [Optionen] --module [/] [args...]\n (zur Ausführung der Hauptklasse in einem Modul)\n oder {0} [Optionen] [args]\n (zur Ausführung eines Programms mit einer Quelldatei)\n\n Argumente, die auf die Hauptklasse, die Quelldatei, -jar , -m oder --module\n / folgen, werden als Argumente für die\nHauptklasse übergeben.\n\n Dabei umfasst "Optionen" Folgendes:\n\n +java.launcher.opt.header = Verwendung: {0} [Optionen] [Argumente...]\n (zur Ausführung einer Klasse)\n oder {0} [Optionen] -jar .jar [Argumente...]\n (zur Ausführung einer JAR-Datei)\n oder {0} [Optionen] -m [/] [Argumente...]\n {0} [Optionen] --module [/] [Argumente...]\n (zur Ausführung der Hauptklasse in einem Modul)\n oder {0} [Optionen] .java [Argumente]\n (zur Ausführung eines Programms mit einer Quelldatei)\n\n Argumente, die auf die Hauptklasse, die Quelldatei, -jar .jar, -m oder --module\n / folgen, werden als Argumente für die\nHauptklasse übergeben.\n\n Dabei umfasst "Optionen" Folgendes:\n\n java.launcher.opt.vmselect =\ {0}\t zur Auswahl der "{1}" VM\n java.launcher.opt.hotspot =\ {0}\t ist ein Synonym für die "{1}" VM [verworfen]\n # Translators please note do not translate the options themselves -java.launcher.opt.footer = \ -cp \n -classpath \n --class-path \n Eine durch {0} getrennte Liste mit Verzeichnissen, JAR-Archiven\n und ZIP-Archiven, in denen nach Klassendateien gesucht wird.\n -p \n --module-path ...\n Eine durch {0} getrennte Liste mit Elementen, von denen jedes Element ein Dateipfad\n zu einem Modul oder einem Verzeichnis mit Modulen ist. Jedes Modul ist entweder\n ein modulares JAR oder ein entpacktes Modulverzeichnis.\n --upgrade-module-path ...\n Eine durch {0} getrennte Liste mit Elementen, von denen jedes Element ein Dateipfad\n zu einem Modul oder einem Verzeichnis mit Modulen ist,\n um upgradefähige Module im Laufzeitimage zu ersetzen. Jedes Modul ist entweder\n ein modulares JAR oder ein entpacktes Modulverzeichnis.\n --add-modules [,...]\n Root-Module, die zusätzlich zum anfänglichen Modul aufgelöst werden sollen.\n kann auch wie folgt lauten: ALL-DEFAULT, ALL-SYSTEM,\n ALL-MODULE-PATH.\n --enable-native-access [,...]\n Damit kann der Code in Modulen auf Code und Daten außerhalb der JRE zugreifen.\n kann auch ALL-UNNAMED sein, um den Code im Classpath anzugeben.\n --list-modules\n Listet beobachtbare Module auf und beendet den Vorgang\n -d \n --describe-module \n Beschreibt ein Modul und beendet den Vorgang\n --dry-run Erstellt eine VM und lädt die Hauptklasse, führt aber nicht die Hauptmethode aus.\n Die Option "--dry-run" kann nützlich sein, um die\n Befehlszeilenoptionen, wie die Modulsystemkonfiguration, zu validieren.\n --validate-modules\n Validiert alle Module und beendet den Vorgang\n Die Option "--validate-modules" kann nützlich sein, um\n Konflikte und andere Fehler mit Modulen auf dem Modulpfad zu ermitteln.\n -D=\n Legt eine Systemeigenschaft fest\n -verbose:[class|module|gc|jni]\n Aktiviert die Verbose-Ausgabe für das angegebene Subsystem\n -version Gibt die Produktversion an den Fehlerstream aus und beendet den Vorgang\n --version Gibt die Produktversion an den Outputstream aus und beendet den Vorgang\n -showversion Gibt die Produktversion an den Fehlerstream aus und setzt den Vorgang fort\n --show-version\n Gibt die Produktversion an den Outputstream aus und setzt den Vorgang fort\n --show-module-resolution\n Zeigt die Modulauflösungsausgabe beim Start an\n -? -h -help\n Gibt diese Hilfemeldung an den Fehlerstream aus\n --help Gibt diese Hilfemeldung an den Outputstream aus\n -X Gibt Hilfe zu zusätzlichen Optionen an den Fehlerstream aus\n --help-extra Gibt Hilfe zu zusätzlichen Optionen an den Outputstream aus\n -ea[:...|:]\n -enableassertions[:...|:]\n Aktiviert Assertions mit angegebener Granularität\n -da[:...|:]\n -disableassertions[:...|:]\n Deaktiviert Assertions mit angegebener Granularität\n -esa | -enablesystemassertions\n Aktiviert System-Assertions\n -dsa | -disablesystemassertions\n Deaktiviert System-Assertions\n -agentlib:[=]\n Lädt die \ -native Agent Library . Beispiel: -agentlib:jdwp\n siehe auch -agentlib:jdwp=help\n -agentpath:[=]\n Lädt die native Agent Library mit dem vollständigen Pfadnamen\n -javaagent:[=]\n Lädt den Java-Programmiersprachen-Agent, siehe java.lang.instrument\n -splash:\n Zeigt den Startbildschirm mit einem angegebenen Bild an\n Skalierte HiDPI-Bilder werden automatisch unterstützt und verwendet,\n falls verfügbar. Der nicht skalierte Bilddateiname (Beispiel: image.ext)\n muss immer als Argument an die Option "-splash" übergeben werden.\n Das am besten geeignete angegebene skalierte Bild wird\n automatisch ausgewählt.\n Weitere Informationen finden Sie in der Dokumentation zur SplashScreen-API\n @argument files\n Eine oder mehrere Argumentdateien mit Optionen\n --disable-@files\n Verhindert die weitere Erweiterung von Argumentdateien\n --enable-preview\n Lässt zu, das Klassen von Vorschaufeatures dieses Release abhängig sind\nUm ein Argument für eine lange Option anzugeben, können Sie --= oder\n-- verwenden.\n +java.launcher.opt.footer = \ -cp \n -classpath \n --class-path \n Eine durch "{0}" getrennte Liste mit Verzeichnissen, JAR-Archiven\n und ZIP-Archiven, in denen nach Klassendateien gesucht wird.\n -p \n --module-path ...\n Eine durch "{0}" getrennte Liste mit Elementen, von denen jedes Element ein Dateipfad ist\n zu einem Modul oder einem Verzeichnis mit Modulen ist. Jedes Modul ist entweder\n ein modulares JAR oder ein entpacktes Modulverzeichnis.\n --upgrade-module-path ...\n Eine durch "{0}" getrennte Liste mit Elementen, von denen jedes Element ein Dateipfad ist\n zu einem Modul oder einem Verzeichnis mit Modulen ist,\n um upgradefähige Module im Laufzeitimage zu ersetzen. Jedes Modul ist entweder\n ein modulares JAR oder ein entpacktes Modulverzeichnis.\n --add-modules [,...]\n Root-Module, die zusätzlich zum anfänglichen Modul aufgelöst werden sollen.\n kann auch wie folgt lauten: ALL-DEFAULT, ALL-SYSTEM,\n ALL-MODULE-PATH.\n --enable-native-access [,...]\n Damit kann der Code in Modulen auf Code und Daten außerhalb der JRE zugreifen.\n kann auch ALL-UNNAMED sein, um den Code im Classpath anzugeben.\n --illegal-native-access=\n Zugriff auf Code und Daten außerhalb der JRE\n durch Code in Modulen zulassen oder verweigern, für die der native Zugriff nicht explizit aktiviert ist.\n ist "deny", "warn" oder "allow". Der Standardwert ist "warn".\n Diese Option wird in einem zukünftigen Release entfernt.\n --list-modules\n Listet beobachtbare Module auf und beendet den Vorgang\n -d \n --describe-module \n Beschreibt ein Modul und beendet den Vorgang\n --dry-run Erstellt eine VM und lädt die Hauptklasse, führt aber nicht die Hauptmethode aus.\n Die Option "--dry-run" kann nützlich sein, um die\n Befehlszeilenoptionen, wie die Modulsystemkonfiguration, zu validieren.\n --validate-modules\n Validiert alle Module und beendet den Vorgang\n Die Option "--validate-modules" kann nützlich sein, um\n Konflikte und andere Fehler mit Modulen auf dem Modulpfad zu ermitteln.\n -D=\n Legt eine Systemeigenschaft fest\n -verbose:[class|module|gc|jni]\n Aktiviert die Verbose-Ausgabe für das angegebene Subsystem\n -version Gibt die Produktversion an den Fehlerstream aus und beendet den Vorgang\n --version Gibt die Produktversion an den Outputstream aus und beendet den Vorgang\n -showversion Gibt die Produktversion an den Fehlerstream aus und setzt den Vorgang fort\n --show-version\n Gibt die Produktversion an den Outputstream aus und setzt den Vorgang fort\n --show-module-resolution\n Zeigt die Modulauflösungsausgabe beim Start an\n -? -h -help\n Gibt diese Hilfemeldung an den Fehlerstream aus\n --help Gibt diese Hilfemeldung an den Outputstream aus\n -X Gibt Hilfe zu zusätzlichen Optionen an den Fehlerstream aus\n --help-extra Gibt Hilfe zu zusätzlichen Optionen an den Outputstream aus\n -ea[:...|:]\n -enableassertions[:...|:]\n Aktiviert Assertions mit angegebener \ +Granularität\n -da[:...|:]\n -disableassertions[:...|:]\n Deaktiviert Assertions mit angegebener Granularität\n -esa | -enablesystemassertions\n Aktiviert System-Assertions\n -dsa | -disablesystemassertions\n Deaktiviert System-Assertions\n -agentlib:[=]\n Lädt die native Agent Library . Beispiel: -agentlib:jdwp\n siehe auch -agentlib:jdwp=help\n -agentpath:[=]\n Lädt die native Agent Library mit dem vollständigen Pfadnamen\n -javaagent:[=]\n Lädt den Java-Programmiersprachen-Agent, siehe java.lang.instrument\n -splash:\n Zeigt den Startbildschirm mit einem angegebenen Bild an\n Skalierte HiDPI-Bilder werden automatisch unterstützt und verwendet,\n falls verfügbar. Der nicht skalierte Bilddateiname (Beispiel: image.ext)\n muss immer als Argument an die Option "-splash" übergeben werden.\n Das am besten geeignete angegebene skalierte Bild wird\n automatisch ausgewählt.\n Weitere Informationen finden Sie in der Dokumentation zur SplashScreen-API\n @argument files\n Eine oder mehrere Argumentdateien mit Optionen\n --disable-@files\n Verhindert die weitere Erweiterung von Argumentdateien\n --enable-preview\n Lässt zu, das Klassen von Vorschaufeatures dieses Release abhängig sind\nUm ein Argument für eine lange Option anzugeben, können Sie --= oder\n-- verwenden.\n # Translators please note do not translate the options themselves -java.launcher.X.usage=\n -Xbatch Deaktiviert die Hintergrundkompilierung\n -Xbootclasspath/a:\n An das Ende des Bootstrap Classpaths anhängen\n -Xcheck:jni Führt zusätzliche Prüfungen für JNI-Funktionen aus\n -Xcomp Erzwingt die Kompilierung von Methoden beim ersten Aufruf\n -Xdebug Führt keine Aktion aus. Ist veraltet und wird in einem zukünftigen Release entfernt.\n -Xdiag Zeigt zusätzliche Diagnosemeldungen an\n -Xfuture Aktiviert strengste Prüfungen, als möglicher zukünftiger Standardwert erwartet.\n Diese Option ist veraltet und kann in einem\n zukünftigen Release entfernt werden.\n -Xint Nur Ausführung im interpretierten Modus\n -Xinternalversion\n Zeigt detailliertere JVM-Versionsinformationen an als die\n Option -version\n -Xlog: Konfiguriert oder aktiviert Logging mit dem einheitlichen Java Virtual\n Machine-(JVM-)Logging-Framework. Verwenden Sie -Xlog:help\n für weitere Einzelheiten.\n -Xloggc: Protokolliert den GC-Status in einer Datei mit Zeitstempeln.\n Diese Option ist veraltet und kann in einem\n zukünftigen Release entfernt werden. Wird durch -Xlog:gc: ersetzt.\n -Xmixed Ausführung im gemischten Modus (Standard)\n -Xmn Legt die anfängliche und maximale Größe (in Byte) des Heaps\n für die Young Generation (Nursery) fest\n -Xms Legt die anfängliche Java-Heap-Größe fest\n -Xmx Legt die maximale Java-Heap-Größe fest\n -Xnoclassgc Deaktiviert die Klassen-Garbage Collection\n -Xrs Reduziert die Verwendung von BS-Signalen durch Java/VM (siehe Dokumentation)\n -Xshare:auto Verwendet freigegebene Klassendaten, wenn möglich (Standard)\n -Xshare:off Versucht nicht, freigegebene Klassendaten zu verwenden\n -Xshare:on Erfordert die Verwendung freigegebener Klassendaten, verläuft sonst nicht erfolgreich.\n Diese Testoption kann zeitweise zu\n Fehlern führen. Sie darf nicht in Produktionsumgebungen verwendet werden.\n -XshowSettings Zeigt alle Einstellungen an und fährt fort\n -XshowSettings:all\n Zeigt alle Einstellungen als Verbose-Ausgabe an und fährt fort\n -XshowSettings:locale\n Zeigt alle gebietsschemabezogenen Einstellungen an und fährt fort\n -XshowSettings:properties\n Zeigt alle Eigenschaftseinstellungen an und fährt fort\n -XshowSettings:vm\n Zeigt alle VM-bezogenen Einstellungen an und fährt fort\n -XshowSettings:security\n Zeigt alle Sicherheitseinstellungen an und fährt fort\n -XshowSettings:security:all\n Zeigt alle Sicherheitseinstellungen an und fährt fort\n -XshowSettings:security:properties\n Zeigt Sicherheitseigenschaften an und fährt fort\n -XshowSettings:security:providers\n Zeigt statische Sicherheitsprovidereinstellungen an und fährt fort\n -XshowSettings:security:tls\n Zeigt TLS-bezogene Sicherheitseinstellungen an und fährt fort\n -XshowSettings:system\n (Nur Linux) Zeigt die Konfiguration des Hostsystems oder Containers an\n und fährt fort\n -Xss Legt die Stackgröße des Java-Threads fest\n Die tatsächliche \ -Größe kann auf ein Vielfaches der\n Systemseitengröße aufgerundet werden, wenn für das Betriebssystem erforderlich.\n -Xverify Legt den Modus der Bytecodeverifizierung fest\n Beachten Sie, dass die Option -Xverify:none veraltet ist und\n in einem zukünftigen Release entfernt werden kann.\n --add-reads =(,)*\n Aktualisiert , damit gelesen wird, ungeachtet\n der Moduldeklaration. \n kann ALL-UNNAMED sein, um alle unbenannten\n Module zu lesen.\n --add-exports /=(,)*\n Aktualisiert , um in zu exportieren,\n ungeachtet der Moduldeklaration.\n kann ALL-UNNAMED sein, um in alle\n unbenannten Module zu exportieren.\n --add-opens /=(,)*\n Aktualisiert , um in\n zu öffnen, ungeachtet der Moduldeklaration.\n --limit-modules [,...]\n Grenzt die Gesamtmenge der beobachtbaren Module ein\n --patch-module =({0})*\n Überschreibt oder erweitert ein Modul mit Klassen und Ressourcen\n in JAR-Dateien oder Verzeichnissen.\n --source \n Legt die Version der Quelle im Quelldateimodus fest.\n --finalization=\n Steuert, ob die JVM Objekte finalisiert.\n Dabei ist entweder "enabled" oder "disabled".\n Die Finalisierung ist standardmäßig aktiviert.\n --sun-misc-unsafe-memory-access=\n Verwendung der nicht unterstützten API sun.misc.Unsafe zulassen oder verweigern\n ist "allow", "warn", "debug" oder "deny".\n Der Standardwert ist "allow".\n\nDiese zusätzlichen Optionen können jederzeit ohne vorherige Ankündigung geändert werden.\n +java.launcher.X.usage=\n -Xbatch Deaktiviert die Hintergrundkompilierung\n -Xbootclasspath/a:\n An das Ende des Bootstrap Classpaths anhängen\n -Xcheck:jni Führt zusätzliche Prüfungen für JNI-Funktionen aus\n -Xcomp Erzwingt die Kompilierung von Methoden beim ersten Aufruf\n -Xdebug Führt keine Aktion aus. Ist veraltet und wird in einem zukünftigen Release entfernt.\n -Xdiag Zeigt zusätzliche Diagnosemeldungen an\n -Xint Nur Ausführung im interpretierten Modus\n -Xinternalversion\n Zeigt detailliertere JVM-Versionsinformationen an als die\n Option -version\n -Xlog: Konfiguriert oder aktiviert Logging mit dem einheitlichen Java Virtual\n Machine-(JVM-)Logging-Framework. Verwenden Sie -Xlog:help\n für weitere Einzelheiten.\n -Xloggc: Protokolliert den GC-Status in einer Datei mit Zeitstempeln.\n Diese Option ist veraltet und kann in einem\n zukünftigen Release entfernt werden. Wird durch -Xlog:gc: ersetzt.\n -Xmixed Ausführung im gemischten Modus (Standard)\n -Xmn Legt die anfängliche und maximale Größe (in Byte) des Heaps\n für die Young Generation (Nursery) fest\n -Xms Legt die anfängliche Java-Heap-Größe fest\n -Xmx Legt die maximale Java-Heap-Größe fest\n -Xnoclassgc Deaktiviert die Klassen-Garbage Collection\n -Xrs Reduziert die Verwendung von BS-Signalen durch Java/VM (siehe Dokumentation)\n -Xshare:auto Verwendet freigegebene Klassendaten, wenn möglich (Standard)\n -Xshare:off Versucht nicht, freigegebene Klassendaten zu verwenden\n -Xshare:on Erfordert die Verwendung freigegebener Klassendaten, verläuft sonst nicht erfolgreich.\n Diese Testoption kann zeitweise zu\n Fehlern führen. Sie darf nicht in Produktionsumgebungen verwendet werden.\n -XshowSettings Zeigt alle Einstellungen an und fährt fort\n -XshowSettings:all\n Zeigt alle Einstellungen als Verbose-Ausgabe an und fährt fort\n -XshowSettings:locale\n Zeigt alle gebietsschemabezogenen Einstellungen an und fährt fort\n -XshowSettings:properties\n Zeigt alle Eigenschaftseinstellungen an und fährt fort\n -XshowSettings:vm\n Zeigt alle VM-bezogenen Einstellungen an und fährt fort\n -XshowSettings:security\n Zeigt alle Sicherheitseinstellungen an und fährt fort\n -XshowSettings:security:all\n Zeigt alle Sicherheitseinstellungen an und fährt fort\n -XshowSettings:security:properties\n Zeigt Sicherheitseigenschaften an und fährt fort\n -XshowSettings:security:providers\n Zeigt statische Sicherheitsprovidereinstellungen an und fährt fort\n -XshowSettings:security:tls\n Zeigt TLS-bezogene Sicherheitseinstellungen an und fährt fort\n -XshowSettings:system\n (Nur Linux) Zeigt die Konfiguration des Hostsystems oder Containers an\n und fährt fort\n -Xss Legt die Stackgröße des Java-Threads fest\n Die tatsächliche Größe kann auf ein Vielfaches der\n Systemseitengröße aufgerundet werden, wenn für das Betriebssystem erforderlich.\n -Xverify Legt den Modus der Bytecodeverifizierung fest\n \ + Beachten Sie, dass die Option -Xverify:none veraltet ist und\n in einem zukünftigen Release entfernt werden kann.\n --add-reads =(,)*\n Aktualisiert , damit gelesen wird, ungeachtet\n der Moduldeklaration. \n kann ALL-UNNAMED sein, um alle unbenannten\n Module zu lesen.\n --add-exports /=(,)*\n Aktualisiert , um in zu exportieren,\n ungeachtet der Moduldeklaration.\n kann ALL-UNNAMED sein, um in alle\n unbenannten Module zu exportieren.\n --add-opens /=(,)*\n Aktualisiert , um in\n zu öffnen, ungeachtet der Moduldeklaration.\n --limit-modules [,...]\n Grenzt die Gesamtmenge der beobachtbaren Module ein\n --patch-module =({0})*\n Überschreibt oder erweitert ein Modul mit Klassen und Ressourcen\n in JAR-Dateien oder Verzeichnissen.\n --source \n Legt die Version der Quelle im Quelldateimodus fest.\n --finalization=\n Steuert, ob die JVM Objekte finalisiert.\n Dabei ist entweder "enabled" oder "disabled".\n Die Finalisierung ist standardmäßig aktiviert.\n --sun-misc-unsafe-memory-access=\n Verwendung der nicht unterstützten API sun.misc.Unsafe zulassen oder verweigern\n ist "allow", "warn", "debug" oder "deny".\n Der Standardwert ist "warn".\n\nDiese zusätzlichen Optionen können jederzeit ohne vorherige Ankündigung geändert werden.\n # Translators please note do not translate the options themselves java.launcher.X.macosx.usage=\nDie folgenden Optionen sind für macOS spezifisch:\n -XstartOnFirstThread\n Führt die main()-Methode für den ersten (AppKit-)Thread aus\n -Xdock:name=\n Setzt den im Dock angezeigten Standardanwendungsnamen außer Kraft\n -Xdock:icon=\n Setzt das im Dock angezeigte Standardsymbol außer Kraft\n\n +# Translators please note do not translate the options themselves +java.launcher.opt.concise.header = Verwendung: java [Java-Optionen...] [Anwendungsargumente...]\n\nDabei ist einer der folgenden Werte:\n Zum Ausführen der Hauptmethode einer kompilierten Hauptklasse\n -jar .jar Zum Ausführen der Hauptklasse eines JAR-Archivs\n -m [/] Zum Ausführen der Hauptklasse eines Moduls\n .java Zum Kompilieren und Ausführen eines Quelldateiprogramms\n\nDabei sind die folgenden wichtigen Java-Optionen verfügbar:\n --class-path \n ist eine durch "{0}" getrennte Liste der Verzeichnisse und JAR-Archive, in denen nach Klassendateien gesucht werden soll\n --module-path \n ist eine durch "{0}" getrennte Liste der Verzeichnisse und JAR-Archive, in denen nach Modulen gesucht werden soll\n -version\n Zum Ausgeben der Produktversion in den Fehlerstream und Beenden des Vorgangs\n\nFür weitere Verwendungshilfe: java --help\nFür eine interaktive Java-Umgebung: jshell + java.launcher.bad.option=\nNicht erkannte showSettings-Option: {0}\nGültige Werte: "all", "locale", "properties", "security", "system"(nur Linux), "vm"\nGültige Werte für Unteroption "security": "all", "properties", "providers", "tls"\nSiehe "java -X"\n java.launcher.cls.error1=Fehler: Hauptklasse {0} konnte nicht gefunden oder geladen werden\nUrsache: {1}: {2} java.launcher.cls.error2=Fehler: Hauptmethode in Klasse {0} nicht gefunden. Definieren Sie die Hauptmethode als:\n public static void main(String[] args):\noder eine JavaFX-Anwendung muss {1} erweitern diff --git a/src/java.base/share/classes/sun/launcher/resources/launcher_ja.properties b/src/java.base/share/classes/sun/launcher/resources/launcher_ja.properties index 5d5223d49c6..c6f1b8b330a 100644 --- a/src/java.base/share/classes/sun/launcher/resources/launcher_ja.properties +++ b/src/java.base/share/classes/sun/launcher/resources/launcher_ja.properties @@ -24,24 +24,27 @@ # # Translators please note do not translate the options themselves -java.launcher.opt.header = 使用方法: {0} [options] [args...]\n (クラスを実行する場合)\n または {0} [options] -jar [args...]\n (jarファイルを実行する場合)\n または {0} [options] -m [/] [args...]\n {0} [options] --module [/] [args...]\n (モジュールのメイン・クラスを実行する場合)\n または {0} [options] [args]\n (ソースファイル・プログラムを実行する場合)\n\n メイン・クラス、ソース・ファイル、-jar 、\n -mまたは--module /に続く引数は、メイン・クラスへの引数として\n 渡されます。\n\n オプションは次のとおりです:\n\n +java.launcher.opt.header = 使用方法: {0} [options] [args...]\n (クラスを実行する場合)\n または {0} [options] -jar .jar [args...]\n (jarファイルを実行する場合)\n または {0} [options] -m [/] [args...]\n {0} [options] --module [/] [args...]\n (モジュールのメイン・クラスを実行する場合)\n または {0} [options] .java [args]\n (ソースファイル・プログラムを実行する場合)\n\n メイン・クラス、ソース・ファイル、-jar .jar、\n-mまたは--module /に続く引数は、メイン・クラスへの引数として\n渡されます。\n\n オプションは次のとおりです:\n\n java.launcher.opt.vmselect =\ {0}\t "{1}" VMを選択する場合\n java.launcher.opt.hotspot =\ {0}\t は"{1}" VMのシノニムです [非推奨]\n # Translators please note do not translate the options themselves -java.launcher.opt.footer = \ -cp <ディレクトリおよびzip/jarファイルのクラス検索パス>\n -classpath <ディレクトリおよびzip/jarファイルのクラス検索パス>\n --class-path <ディレクトリおよびzip/jarファイルのクラス検索パス>\n {0}区切りリスト(ディレクトリ、JARアーカイブ、\n ZIPアーカイブ)で、クラス・ファイルの検索用。\n -p \n --module-path ...\n 要素を{0}で区切ったリストで、各要素は次へのファイル・パスです:\n モジュール、またはモジュールが格納されているディレクトリ。各モジュールは次のいずれかです:\n モジュラJARまたは展開形式のモジュール・ディレクトリ。\n --upgrade-module-path ...\n 要素を{0}で区切ったリストで、各要素は次へのファイル・パスです:\n モジュール、またはモジュールが格納されているディレクトリで、次のものを置き換えます:\n ランタイム・イメージのアップグレード可能なモジュール。各モジュールは次のいずれかです:\n モジュラJARまたは展開形式のモジュール・ディレクトリ。\n --add-modules [,...]\n 初期モジュールに加えて解決するルート・モジュール。\n には次も指定できます: ALL-DEFAULT、ALL-SYSTEM、\n ALL-MODULE-PATH.\n --enable-native-access [,...]\n モジュール内のコードをJavaランタイムの外のコードおよびデータにアクセスさせることができます。\n は、クラス・パス上のコードを指定するためにALL-UNNAMEDにもできます。\n --list-modules\n 参照可能なモジュールをリストし終了します\n -d \n --describe-module \n モジュールを説明し終了します\n --dry-run VMを作成しメイン・クラスをロードしますが、メイン・メソッドは実行しません。\n \ ---dry-runオプションは、次の検証に役立つ場合があります:\n モジュール・システム構成などのコマンド行オプション。\n --validate-modules\n すべてのモジュールを検証し終了します\n --validate-modulesオプションは、次の検索に役立つ場合があります:\n モジュール・パス上のモジュールでの競合およびその他のエラー。\n -D=\n システム・プロパティを設定します\n -verbose:[class|module|gc|jni]\n 特定のサブシステムで詳細出力を有効にする\n -version 製品バージョンをエラー・ストリームに出力して終了します\n --version 製品バージョンを出力ストリームに出力して終了します\n -showversion 製品バージョンをエラー・ストリームに出力して続行します\n --show-version\n 製品バージョンを出力ストリームに出力して続行します\n --show-module-resolution\n 起動時にモジュール解決出力を表示します\n -? -h -help\n このヘルプ・メッセージをエラー・ストリームに出力します\n --help このヘルプ・メッセージを出力ストリームに出力します\n -X 追加オプションのヘルプをエラー・ストリームに出力します\n --help-extra 追加オプションのヘルプを出力ストリームに出力します\n -ea[:...|:]\n -enableassertions[:...|:]\n 指定した粒度でアサーションを有効にします\n -da[:...|:]\n -disableassertions[:...|:]\n 指定した粒度でアサーションを無効にします\n -esa | -enablesystemassertions\n システム・アサーションを有効にします\n -dsa | -disablesystemassertions\n システム・アサーションを無効にします\n -agentlib:[=]\n ネイティブ・エージェント・ライブラリをロードします。例: -agentlib:jdwp\n -agentlib:jdwp=helpも参照してください\n -agentpath:[=]\n \ -フルパス名を使用して、ネイティブ・エージェント・ライブラリをロードします\n -javaagent:[=]\n Javaプログラミング言語エージェントをロードします。java.lang.instrumentを参照してください\n -splash:\n 指定されたイメージを含むスプラッシュ画面を表示します\n HiDPIスケールのイメージが自動的にサポートされて使用されます\n (可能な場合)。スケーリングされないイメージのファイル名(image.extなど)を\n 引数として-splashオプションに必ず渡す必要があります。\n 指定された最も適切なスケーリング済イメージが選択されます\n (自動的)。\n 詳細は、SplashScreen APIのドキュメントを参照してください\n @argumentファイル\n オプションを含む1つ以上の引数ファイル\n --disable-@files\n さらなる引数ファイル拡張を無効にします\n --enable-preview\n クラスをこのリリースのプレビュー機能に依存させることができます\n長いオプションの引数を指定する場合、--=または\n-- を使用できます。\n +java.launcher.opt.footer = \ -cp <ディレクトリおよびzip/jarファイルのクラス検索パス>\n -classpath <ディレクトリおよびzip/jarファイルのクラス検索パス>\n --class-path <ディレクトリおよびzip/jarファイルのクラス検索パス>\n "{0}"区切りリスト(ディレクトリ、JARアーカイブ、\n ZIPアーカイブ)で、クラス・ファイルの検索用。\n -p \n --module-path ...\n 要素を"{0}"で区切ったリストで、各要素は次へのファイル・パスです:\n モジュール、またはモジュールが格納されているディレクトリ。各モジュールは次のいずれかです:\n モジュラJARまたは展開形式のモジュール・ディレクトリ。\n --upgrade-module-path ...\n 要素を"{0}"で区切ったリストで、各要素は次へのファイル・パスです:\n モジュール、またはモジュールが格納されているディレクトリで、次のものを置き換えます:\n ランタイム・イメージのアップグレード可能なモジュール。各モジュールは次のいずれかです:\n モジュラJARまたは展開形式のモジュール・ディレクトリ。\n --add-modules [,...]\n 初期モジュールに加えて解決するルート・モジュール。\n には次も指定できます: ALL-DEFAULT、ALL-SYSTEM、\n ALL-MODULE-PATH.\n --enable-native-access [,...]\n モジュール内のコードをJavaランタイムの外のコードおよびデータにアクセスさせることができます。\n は、クラス・パス上のコードを指定するためにALL-UNNAMEDにもできます。\n --illegal-native-access=\n Javaランタイムの外のコードおよびデータへのアクセスを許可または拒否します\n (ネイティブ・アクセスが明示的に有効化されていないモジュール内のコードによる)。\n \ +は、"deny"、"warn"または"allow"のいずれかです。デフォルト値は"warn"です。\n このオプションは、将来のリリースで削除される予定です。\n --list-modules\n 参照可能なモジュールをリストし終了します\n -d \n --describe-module \n モジュールを説明し終了します\n --dry-run VMを作成しメイン・クラスをロードしますが、メイン・メソッドは実行しません。\n --dry-runオプションは、次の検証に役立つ場合があります:\n モジュール・システム構成などのコマンド行オプション。\n --validate-modules\n すべてのモジュールを検証し終了します\n --validate-modulesオプションは、次の検索に役立つ場合があります:\n モジュール・パス上のモジュールでの競合およびその他のエラー。\n -D=\n システム・プロパティを設定します\n -verbose:[class|module|gc|jni]\n 特定のサブシステムで詳細出力を有効にする\n -version 製品バージョンをエラー・ストリームに出力して終了します\n --version 製品バージョンを出力ストリームに出力して終了します\n -showversion 製品バージョンをエラー・ストリームに出力して続行します\n --show-version\n 製品バージョンを出力ストリームに出力して続行します\n --show-module-resolution\n 起動時にモジュール解決出力を表示します\n -? -h -help\n このヘルプ・メッセージをエラー・ストリームに出力します\n --help このヘルプ・メッセージを出力ストリームに出力します\n -X 追加オプションのヘルプをエラー・ストリームに出力します\n --help-extra 追加オプションのヘルプを出力ストリームに出力します\n -ea[:...|:]\n -enableassertions[:...|:]\n 指定した粒度でアサーションを有効にします\n -da[:...|:]\n \ +-disableassertions[:...|:]\n 指定した粒度でアサーションを無効にします\n -esa | -enablesystemassertions\n システム・アサーションを有効にします\n -dsa | -disablesystemassertions\n システム・アサーションを無効にします\n -agentlib:[=]\n ネイティブ・エージェント・ライブラリをロードします。例: -agentlib:jdwp\n -agentlib:jdwp=helpも参照してください\n -agentpath:[=]\n フルパス名を使用して、ネイティブ・エージェント・ライブラリをロードします\n -javaagent:[=]\n Javaプログラミング言語エージェントをロードします。java.lang.instrumentを参照してください\n -splash:\n 指定されたイメージを含むスプラッシュ画面を表示します\n HiDPIスケールのイメージが自動的にサポートされて使用されます\n (可能な場合)。スケーリングされないイメージのファイル名(image.extなど)を\n 引数として-splashオプションに必ず渡す必要があります。\n 指定された最も適切なスケーリング済イメージが選択されます\n (自動的)。\n 詳細は、SplashScreen APIのドキュメントを参照してください\n @argumentファイル\n オプションを含む1つ以上の引数ファイル\n --disable-@files\n さらなる引数ファイル拡張を無効にします\n --enable-preview\n クラスをこのリリースのプレビュー機能に依存させることができます\n長いオプションの引数を指定する場合、--=または\n-- を使用できます。\n # Translators please note do not translate the options themselves -java.launcher.X.usage=\n -Xbatch バックグラウンド・コンパイルを無効にします\n -Xbootclasspath/a:\n ブートストラップ・クラス・パスの最後に追加します\n -Xcheck:jni JNI関数に対する追加のチェックを実行します\n -Xcomp 初回呼出し時にメソッドのコンパイルを強制します\n -Xdebug 何も実行されません。将来のリリースで削除されるため、非推奨になりました。\n -Xdiag 追加の診断メッセージを表示します\n -Xfuture 将来のデフォルトを見越して、最も厳密なチェックを有効にします\n このオプションは非推奨であり、将来のリリースで削除される\n 可能性があります。\n -Xint インタプリタ・モードの実行のみ\n -Xinternalversion\n -versionオプションより詳細なJVMバージョン情報を\n 表示します\n -Xlog: Java Virtual Machine (JVM)統合ロギング・フレームワークでの\n ロギングを構成または有効化します。詳細は、-Xlog:helpを\n 使用してください。\n -Xloggc: タイムスタンプが付いたファイルにGCステータスのログを記録します\n このオプションは非推奨であり、将来のリリースで削除される\n 可能性があります。-Xlog:gc:で置換されています。\n -Xmixed 混合モードの実行(デフォルト)\n -Xmn 若い世代(ナーサリ)のヒープの初期サイズおよび最大サイズ\n (バイト単位)を設定します\n -Xms Javaの初期ヒープ・サイズを設定します\n -Xmx Javaの最大ヒープ・サイズを設定します\n -Xnoclassgc クラスのガベージ・コレクションを無効にします\n -Xrs Java/VMによるOSシグナルの使用を削減します(ドキュメントを参照)\n -Xshare:auto 可能であれば共有クラス・データを使用します(デフォルト)\n -Xshare:off \ -共有クラス・データの使用を試みません\n -Xshare:on 共有クラス・データの使用を必須にし、できなければ失敗します。\n これはテスト・オプションであり、断続的な失敗につながる\n 可能性があります。本番環境では使用しないでください。\n -XshowSettings すべての設定を表示して続行します\n -XshowSettings:all\n すべての設定を詳細に表示して続行します\n -XshowSettings:locale\n すべてのロケール関連の設定を表示して続行します\n -XshowSettings:properties\n すべてのプロパティ設定を表示して続行します\n -XshowSettings:vm\n すべてのVM関連の設定を表示して続行します\n -XshowSettings:security\n すべてのセキュリティ設定を表示して続行します\n -XshowSettings:security:all\n すべてのセキュリティ設定を表示して続行します\n -XshowSettings:security:properties\n セキュリティ・プロパティを表示して続行します\n -XshowSettings:security:providers\n 静的セキュリティ・プロバイダ設定を表示して続行します\n -XshowSettings:security:tls\n TLS関連のセキュリティ設定を表示して続行します\n -XshowSettings:system\n (Linuxのみ)ホスト・システムまたはコンテナを表示します\n 構成して続行します\n -Xss javaスレッドのスタック・サイズを設定します\n 実際のサイズは、次の倍数に切り上げられる場合があります: \n オペレーティング・システムの要件に応じたシステム・ページ・サイズ。\n -Xverify バイトコード・ベリファイアのモードを設定します\n オプション-Xverify:noneは非推奨になり、\n 将来のリリースで削除される可能性があります。\n --add-reads =(,)*\n モジュール宣言に関係なく、を更新してを\n \ -読み取ります。 \n をALL-UNNAMEDに設定すると、すべての名前のないモジュールを\n 読み取ることができます。\n --add-exports /=(,)*\n モジュール宣言に関係なく、を更新してに\n エクスポートします。\n をALL-UNNAMEDに設定すると、すべての名前のないモジュールに\n エクスポートできます。\n --add-opens /=(,)*\n モジュール宣言に関係なく、を更新してを\n に開きます。\n --limit-modules [,...]\n 参照可能なモジュールの領域を制限します\n --patch-module =({0})*\n JARファイルまたはディレクトリのクラスおよびリソースで\n モジュールをオーバーライドまたは拡張します。\n --source \n ソースファイル・モードでソースのバージョンを設定します。\n --finalization=\n JVMがオブジェクトのファイナライズを実行するかどうかを制御します\n は"enabled"または"disabled"のいずれかです。\n ファイナライズはデフォルトで有効になっています。\n --sun-misc-unsafe-memory-access=\n サポートされていないAPI sun.misc.Unsafeの使用を許可または拒否します\n は"allow"、"warn"、"debug"または"deny"のいずれかです。\n デフォルト値は、"allow"です。\n\nこの追加オプションは予告なしに変更されることがあります。\n +java.launcher.X.usage=\n -Xbatch バックグラウンド・コンパイルを無効にします\n -Xbootclasspath/a:\n ブートストラップ・クラス・パスの最後に追加します\n -Xcheck:jni JNI関数に対する追加のチェックを実行します\n -Xcomp 初回呼出し時にメソッドのコンパイルを強制します\n -Xdebug 何も実行されません。将来のリリースで削除されるため、非推奨になりました。\n -Xdiag 追加の診断メッセージを表示します\n -Xint インタプリタ・モードの実行のみ\n -Xinternalversion\n -versionオプションより詳細なJVMバージョン情報を\n 表示します\n -Xlog: Java Virtual Machine (JVM)統合ロギング・フレームワークでの\n ロギングを構成または有効化します。詳細は、-Xlog:helpを\n 使用してください。\n -Xloggc: タイムスタンプが付いたファイルにGCステータスのログを記録します\n このオプションは非推奨であり、将来のリリースで削除される\n 可能性があります。-Xlog:gc:で置換されています。\n -Xmixed 混合モードの実行(デフォルト)\n -Xmn 若い世代(ナーサリ)のヒープの初期サイズおよび最大サイズ\n (バイト単位)を設定します\n -Xms Javaの初期ヒープ・サイズを設定します\n -Xmx Javaの最大ヒープ・サイズを設定します\n -Xnoclassgc クラスのガベージ・コレクションを無効にします\n -Xrs Java/VMによるOSシグナルの使用を削減します(ドキュメントを参照)\n -Xshare:auto 可能であれば共有クラス・データを使用します(デフォルト)\n -Xshare:off 共有クラス・データの使用を試みません\n -Xshare:on 共有クラス・データの使用を必須にし、できなければ失敗します。\n \ +これはテスト・オプションであり、断続的な失敗につながる\n 可能性があります。本番環境では使用しないでください。\n -XshowSettings すべての設定を表示して続行します\n -XshowSettings:all\n すべての設定を詳細に表示して続行します\n -XshowSettings:locale\n すべてのロケール関連の設定を表示して続行します\n -XshowSettings:properties\n すべてのプロパティ設定を表示して続行します\n -XshowSettings:vm\n すべてのVM関連の設定を表示して続行します\n -XshowSettings:security\n すべてのセキュリティ設定を表示して続行します\n -XshowSettings:security:all\n すべてのセキュリティ設定を表示して続行します\n -XshowSettings:security:properties\n セキュリティ・プロパティを表示して続行します\n -XshowSettings:security:providers\n 静的セキュリティ・プロバイダ設定を表示して続行します\n -XshowSettings:security:tls\n TLS関連のセキュリティ設定を表示して続行します\n -XshowSettings:system\n (Linuxのみ)ホスト・システムまたはコンテナを表示します\n 構成して続行します\n -Xss javaスレッドのスタック・サイズを設定します\n 実際のサイズは、次の倍数に切り上げられる場合があります: \n オペレーティング・システムの要件に応じたシステム・ページ・サイズ。\n -Xverify バイトコード・ベリファイアのモードを設定します\n オプション-Xverify:noneは非推奨になり、\n 将来のリリースで削除される可能性があります。\n --add-reads =(,)*\n モジュール宣言に関係なく、を更新してを\n 読み取ります。 \n をALL-UNNAMEDに設定すると、すべての名前のないモジュールを\n 読み取ることができます。\n --add-exports \ +/=(,)*\n モジュール宣言に関係なく、を更新してに\n エクスポートします。\n をALL-UNNAMEDに設定すると、すべての名前のないモジュールに\n エクスポートできます。\n --add-opens /=(,)*\n モジュール宣言に関係なく、を更新してを\n に開きます。\n --limit-modules [,...]\n 参照可能なモジュールの領域を制限します\n --patch-module =({0})*\n JARファイルまたはディレクトリのクラスおよびリソースで\n モジュールをオーバーライドまたは拡張します。\n --source \n ソースファイル・モードでソースのバージョンを設定します。\n --finalization=\n JVMがオブジェクトのファイナライズを実行するかどうかを制御します\n は"enabled"または"disabled"のいずれかです。\n ファイナライズはデフォルトで有効になっています。\n --sun-misc-unsafe-memory-access=\n サポートされていないAPI sun.misc.Unsafeの使用を許可または拒否します\n は"allow"、"warn"、"debug"または"deny"のいずれかです。\n デフォルト値は"warn"です。\n\nこの追加オプションは予告なしに変更されることがあります。\n # Translators please note do not translate the options themselves java.launcher.X.macosx.usage=\n次のオプションはmacOS固有です:\n -XstartOnFirstThread\n main()メソッドを最初(AppKit)のスレッドで実行する\n -Xdock:name=\n Dockに表示されるデフォルト・アプリケーション名をオーバーライドする\n -Xdock:icon=\n Dockに表示されるデフォルト・アイコンをオーバーライドする\n\n +# Translators please note do not translate the options themselves +java.launcher.opt.concise.header = 使用方法: java [java options...] [application arguments...]\n\nは次のいずれかです:\n コンパイルされたメイン・クラスのメイン・メソッドを実行します\n -jar .jar JARアーカイブのメイン・クラスを実行します\n -m [/] モジュールのメイン・クラスを実行します\n .java ソースファイル・プログラムをコンパイルおよび実行します\n\n主要なjavaオプションには次が含まれます:\n --class-path \n は、クラス・ファイルを検索するためのディレクトリおよびJARアーカイブのリストであり、"{0}"で区切られます\n --module-path \n は、モジュールを検索するためのディレクトリおよびJARアーカイブのリストであり、"{0}"で区切られます\n -version\n 製品バージョンをエラー・ストリームに出力し終了します\n\n使用方法についての追加のヘルプの場合: java --help\n対話型のJava環境の場合: jshell + java.launcher.bad.option=\n認識されないshowSettingsオプション: {0}\n有効な値は"all"、"locale"、"properties"、"security"、"system"(Linuxのみ)、"vm"\n有効な"security"サブオプションの値は"all"、"properties"、"providers"、"tls"\n"java -X"を参照してください\n java.launcher.cls.error1=エラー: メイン・クラス{0}を検出およびロードできませんでした\n原因: {1}: {2} java.launcher.cls.error2=エラー: メイン・メソッドがクラス{0}で見つかりません。次のようにメイン・メソッドを定義してください。\n public static void main(String[] args)\nまたはJavaFXアプリケーション・クラスは{1}を拡張する必要があります diff --git a/src/java.base/share/classes/sun/launcher/resources/launcher_zh_CN.properties b/src/java.base/share/classes/sun/launcher/resources/launcher_zh_CN.properties index c156e234cef..56d774b47db 100644 --- a/src/java.base/share/classes/sun/launcher/resources/launcher_zh_CN.properties +++ b/src/java.base/share/classes/sun/launcher/resources/launcher_zh_CN.properties @@ -24,22 +24,25 @@ # # Translators please note do not translate the options themselves -java.launcher.opt.header = 用法:{0} [options] [args...]\n (执行类)\n 或 {0} [options] -jar [args...]\n (执行 jar 文件)\n 或 {0} [options] -m [/] [args...]\n {0} [options] --module [/] [args...]\n (执行模块中的主类)\n 或 {0} [options] [args]\n (执行源文件程序)\n\n 将主类、源文件、-jar 、-m 或\n --module / 后的参数作为参数\n 传递到主类。\n\n 其中,选项包括:\n\n +java.launcher.opt.header = 用法:{0} [options] [args...]\n (执行类)\n 或 {0} [options] -jar .jar [args...]\n (执行 jar 文件)\n 或 {0} [options] -m [/] [args...]\n {0} [options] --module [/] [args...]\n (执行模块中的主类)\n 或 {0} [options] .java [args]\n (执行源文件程序)\n\n 将主类、源文件、-jar .jar、-m 或\n --module / 后的参数作为参数\n 传递到主类。\n\n 其中,选项包括:\n\n java.launcher.opt.vmselect =\ {0}\t 选择 "{1}" VM\n java.launcher.opt.hotspot =\ {0}\t 是 "{1}" VM 的同义词 [已过时]\n # Translators please note do not translate the options themselves -java.launcher.opt.footer = \ -cp <目录和 zip/jar 文件的类搜索路径>\n -classpath <目录和 zip/jar 文件的类搜索路径>\n --class-path <目录和 zip/jar 文件的类搜索路径>\n 使用 {0} 分隔的, 用于搜索类文件的目录, JAR 档案\n 和 ZIP 档案列表。\n -p <模块路径>\n --module-path <模块路径>...\n {0} 分隔的元素列表,每个元素都是\n 模块或包含模块的目录的文件路径。每个模块都是\n 模块化 JAR 或展开的模块目录。\n --upgrade-module-path <模块路径>...\n {0} 分隔的元素列表,每个元素都是\n 模块或包含模块(用于替换运行时映像中的\n 可升级模块)的目录的文件路径。每个模块都是\n 模块化 JAR 或展开的模块目录。\n --add-modules <模块名称>[,<模块名称>...]\n 除了初始模块之外要解析的根模块。\n <模块名称> 还可以为 ALL-DEFAULT, ALL-SYSTEM,\n ALL-MODULE-PATH.\n --enable-native-access [,...]\n 允许模块中的代码访问 Java 运行时之外的代码和数据。\n 也可以是 ALL-UNNAMED,以指示类路径上的代码。\n --list-modules\n 列出可观察模块并退出\n -d \n --describe-module <模块名称>\n 描述模块并退出\n --dry-run 创建 VM 并加载主类, 但不执行 main 方法。\n 此 --dry-run 选项对于验证诸如\n 模块系统配置这样的命令行选项可能非常有用。\n --validate-modules\n 验证所有模块并退出\n --validate-modules 选项对于查找\n 模块路径中模块的冲突及其他错误可能非常有用。\n -D<名称>=<值>\n 设置系统属性\n -verbose:[class|module|gc|jni]\n 为给定子系统启用详细输出\n -version 将产品版本输出到错误流并退出\n --version 将产品版本输出到输出流并退出\n -showversion 将产品版本输出到错误流并继续\n --show-version\n 将产品版本输出到输出流并继续\n --show-module-resolution\n 在启动过程中显示模块解析输出\n -? -h -help\n 将此帮助消息输出到错误流\n --help \ -将此帮助消息输出到输出流\n -X 将额外选项的帮助输出到错误流\n --help-extra 将额外选项的帮助输出到输出流\n -ea[:<程序包名称>...|:<类名>]\n -enableassertions[:<程序包名称>...|:<类名>]\n 按指定的粒度启用断言\n -da[:<程序包名称>...|:<类名>]\n -disableassertions[:<程序包名称>...|:<类名>]\n 按指定的粒度禁用断言\n -esa | -enablesystemassertions\n 启用系统断言\n -dsa | -disablesystemassertions\n 禁用系统断言\n -agentlib:<库名>[=<选项>]\n 加载本机代理库 <库名>, 例如 -agentlib:jdwp\n 另请参阅 -agentlib:jdwp=help\n -agentpath:<路径名>[=<选项>]\n 按完整路径名加载本机代理库\n -javaagent:[=<选项>]\n 加载 Java 编程语言代理, 请参阅 java.lang.instrument\n -splash:<图像路径>\n 使用指定的图像显示启动屏幕\n 自动支持和使用 HiDPI 缩放图像\n (如果可用)。应始终将未缩放的图像文件名 (例如, image.ext)\n 作为参数传递给 -splash 选项。\n 将自动选取提供的最合适的缩放\n 图像。\n 有关详细信息, 请参阅 SplashScreen API 文档\n @argument 文件\n 一个或多个包含选项的参数文件\n --disable-@files\n 阻止进一步扩展参数文件\n --enable-preview\n 允许类依赖于此发行版的预览功能\n要为长选项指定参数, 可以使用 --<名称>=<值> 或\n--<名称> <值>。\n +java.launcher.opt.footer = \ -cp <目录和 zip/jar 文件的类搜索路径>\n -classpath <目录和 zip/jar 文件的类搜索路径>\n --class-path <目录和 zip/jar 文件的类搜索路径>\n 以 "{0}" 分隔的用于搜索类文件的目录、JAR 档案\n 和 ZIP 档案列表。\n -p <模块路径>\n --module-path <模块路径>...\n 以 "{0}" 分隔的元素列表,每个元素都是\n 模块或包含模块的目录的文件路径。每个模块都是\n 模块化 JAR 或展开的模块目录。\n --upgrade-module-path <模块路径>...\n 以 "{0}" 分隔的元素列表,每个元素都是\n 模块或包含模块(用于替换运行时映像中的\n 可升级模块)的目录的文件路径。每个模块都是\n 模块化 JAR 或展开的模块目录。\n --add-modules <模块名称>[,<模块名称>...]\n 除了初始模块之外要解析的根模块。\n <模块名称> 还可以为 ALL-DEFAULT, ALL-SYSTEM,\n ALL-MODULE-PATH.\n --enable-native-access [,...]\n 允许模块中的代码访问 Java 运行时之外的代码和数据。\n 也可以是 ALL-UNNAMED,以指示类路径上的代码。\n --illegal-native-access=\n 允许或拒绝模块中没有明确为其启用本机访问的\n 代码访问 Java 运行时之外的代码和数据。\n 为 "deny"、"warn" 或 "allow" 之一。默认值为 "warn"。\n 此选项将在未来发行版中删除。\n --list-modules\n 列出可观察模块并退出\n -d \n --describe-module <模块名称>\n 描述模块并退出\n --dry-run 创建 VM 并加载主类, 但不执行 main 方法。\n 此 --dry-run 选项对于验证诸如\n 模块系统配置这样的命令行选项可能非常有用。\n --validate-modules\n 验证所有模块并退出\n --validate-modules 选项对于查找\n 模块路径中模块的冲突及其他错误可能非常有用。\n -D<名称>=<值>\n 设置系统属性\n -verbose:[class|module|gc|jni]\n 为给定子系统启用详细输出\n -version 将产品版本输出到错误流并退出\n --version \ +将产品版本输出到输出流并退出\n -showversion 将产品版本输出到错误流并继续\n --show-version\n 将产品版本输出到输出流并继续\n --show-module-resolution\n 在启动过程中显示模块解析输出\n -? -h -help\n 将此帮助消息输出到错误流\n --help 将此帮助消息输出到输出流\n -X 将额外选项的帮助输出到错误流\n --help-extra 将额外选项的帮助输出到输出流\n -ea[:<程序包名称>...|:<类名>]\n -enableassertions[:<程序包名称>...|:<类名>]\n 按指定的粒度启用断言\n -da[:<程序包名称>...|:<类名>]\n -disableassertions[:<程序包名称>...|:<类名>]\n 按指定的粒度禁用断言\n -esa | -enablesystemassertions\n 启用系统断言\n -dsa | -disablesystemassertions\n 禁用系统断言\n -agentlib:<库名>[=<选项>]\n 加载本机代理库 <库名>, 例如 -agentlib:jdwp\n 另请参阅 -agentlib:jdwp=help\n -agentpath:<路径名>[=<选项>]\n 按完整路径名加载本机代理库\n -javaagent:[=<选项>]\n 加载 Java 编程语言代理, 请参阅 java.lang.instrument\n -splash:<图像路径>\n 使用指定的图像显示启动屏幕\n 自动支持和使用 HiDPI 缩放图像\n (如果可用)。应始终将未缩放的图像文件名 (例如, image.ext)\n 作为参数传递给 -splash 选项。\n 将自动选取提供的最合适的缩放\n 图像。\n 有关详细信息, 请参阅 SplashScreen API 文档\n @argument 文件\n 一个或多个包含选项的参数文件\n --disable-@files\n 阻止进一步扩展参数文件\n --enable-preview\n 允许类依赖于此发行版的预览功能\n要为长选项指定参数, 可以使用 --<名称>=<值> 或\n--<名称> <值>。\n # Translators please note do not translate the options themselves -java.launcher.X.usage=\n -Xbatch 禁用后台编译\n -Xbootclasspath/a:<以 {0} 分隔的目录和 zip/jar 文件>\n 附加在引导类路径末尾\n -Xcheck:jni 对 JNI 函数执行其他检查\n -Xcomp 强制在首次调用时编译方法\n -Xdebug 不执行任何操作;已过时,将在未来发行版中删除。\n -Xdiag 显示附加诊断消息\n -Xfuture 启用最严格的检查,预期将来的默认值。\n 此选项已过时,可能会在\n 未来发行版中删除。\n -Xint 仅解释模式执行\n -Xinternalversion\n 显示比 -version 选项更详细的\n JVM 版本信息\n -Xlog: 配置或启用采用 Java 虚拟\n 机 (Java Virtual Machine, JVM) 统一记录框架进行事件记录。使用 -Xlog:help\n 可了解详细信息。\n -Xloggc: 将 GC 状态记录在文件中(带时间戳)。\n 此选项已过时,可能会在\n 将来的发行版中删除。它将替换为 -Xlog:gc:。\n -Xmixed 混合模式执行(默认值)\n -Xmn 为年轻代(新生代)设置初始和最大堆大小\n (以字节为单位)\n -Xms 设置初始 Java 堆大小\n -Xmx 设置最大 Java 堆大小\n -Xnoclassgc 禁用类垃圾收集\n -Xrs 减少 Java/VM 对操作系统信号的使用(请参见文档)\n -Xshare:auto 在可能的情况下使用共享类数据(默认值)\n -Xshare:off 不尝试使用共享类数据\n -Xshare:on 要求使用共享类数据,否则将失败。\n 这是一个测试选项,可能导致间歇性\n 故障。不应在生产环境中使用它。\n -XshowSettings 显示所有设置并继续\n -XshowSettings:all\n 详细显示所有设置并继续\n -XshowSettings:locale\n 显示所有与区域设置相关的设置并继续\n -XshowSettings:properties\n 显示所有属性设置并继续\n -XshowSettings:vm\n 显示所有与 vm 相关的设置并继续\n -XshowSettings:security\n 显示所有安全设置并继续\n -XshowSettings:security:all\n 显示所有安全设置并继续\n -XshowSettings:security:properties\n \ - 显示安全属性并继续\n -XshowSettings:security:providers\n 显示静态安全提供方设置并继续\n -XshowSettings:security:tls\n 显示与 TLS 相关的安全设置并继续\n -XshowSettings:system\n (仅 Linux)显示主机系统或容器\n 配置并继续\n -Xss 设置 Java 线程堆栈大小\n 实际大小可以舍入到\n 操作系统要求的系统页面大小的倍数。\n -Xverify 设置字节码验证器的模式\n 请注意,选项 -Xverify:none 已过时,\n 可能会在未来发行版中删除。\n --add-reads =(,)*\n 更新 以读取 ,而无论\n 模块如何声明。 \n 可以是 ALL-UNNAMED,将读取所有未命名\n 模块。\n --add-exports /=(,)*\n 更新 以将 导出到 ,\n 而无论模块如何声明。\n 可以是 ALL-UNNAMED,将导出到所有\n 未命名模块。\n --add-opens /=(,)*\n 更新 以在 中打开\n ,而无论模块如何声明。\n --limit-modules [,...]\n 限制可观察模块的领域\n --patch-module =({0})*\n 使用 JAR 文件或目录中的类和资源\n 覆盖或增强模块。\n --source \n 设置源文件模式中源的版本。\n --finalization=\n 控制 JVM 是否执行对象最终处理,\n 其中 为 "enabled" 或 "disabled" 之一。\n 默认情况下,最终处理处于启用状态。\n --sun-misc-unsafe-memory-access=\n 允许或拒绝使用不受支持的 API sun.misc.Unsafe\n 为 "allow"、"warn"、"debug" 或 "deny" 之一。\n 默认值为 "allow"。\n\n这些额外选项如有更改, 恕不另行通知。\n +java.launcher.X.usage=\n -Xbatch 禁用后台编译\n -Xbootclasspath/a:<以 {0} 分隔的目录和 zip/jar 文件>\n 附加在引导类路径末尾\n -Xcheck:jni 对 JNI 函数执行其他检查\n -Xcomp 强制在首次调用时编译方法\n -Xdebug 不执行任何操作;已过时,将在未来发行版中删除。\n -Xdiag 显示附加诊断消息\n -Xint 仅解释模式执行\n -Xinternalversion\n 显示比 -version 选项更详细的\n JVM 版本信息\n -Xlog: 配置或启用采用 Java 虚拟\n 机 (Java Virtual Machine, JVM) 统一记录框架进行事件记录。使用 -Xlog:help\n 可了解详细信息。\n -Xloggc: 将 GC 状态记录在文件中(带时间戳)。\n 此选项已过时,可能会在\n 将来的发行版中删除。它将替换为 -Xlog:gc:。\n -Xmixed 混合模式执行(默认值)\n -Xmn 为年轻代(新生代)设置初始和最大堆大小\n (以字节为单位)\n -Xms 设置初始 Java 堆大小\n -Xmx 设置最大 Java 堆大小\n -Xnoclassgc 禁用类垃圾收集\n -Xrs 减少 Java/VM 对操作系统信号的使用(请参见文档)\n -Xshare:auto 在可能的情况下使用共享类数据(默认值)\n -Xshare:off 不尝试使用共享类数据\n -Xshare:on 要求使用共享类数据,否则将失败。\n 这是一个测试选项,可能导致间歇性\n 故障。不应在生产环境中使用它。\n -XshowSettings 显示所有设置并继续\n -XshowSettings:all\n 详细显示所有设置并继续\n -XshowSettings:locale\n 显示所有与区域设置相关的设置并继续\n -XshowSettings:properties\n 显示所有属性设置并继续\n -XshowSettings:vm\n 显示所有与 vm 相关的设置并继续\n -XshowSettings:security\n 显示所有安全设置并继续\n -XshowSettings:security:all\n 显示所有安全设置并继续\n -XshowSettings:security:properties\n 显示安全属性并继续\n -XshowSettings:security:providers\n 显示静态安全提供方设置并继续\n -XshowSettings:security:tls\n 显示与 TLS \ +相关的安全设置并继续\n -XshowSettings:system\n (仅 Linux)显示主机系统或容器\n 配置并继续\n -Xss 设置 Java 线程堆栈大小\n 实际大小可以舍入到\n 操作系统要求的系统页面大小的倍数。\n -Xverify 设置字节码验证器的模式\n 请注意,选项 -Xverify:none 已过时,\n 可能会在未来发行版中删除。\n --add-reads =(,)*\n 更新 以读取 ,而无论\n 模块如何声明。 \n 可以是 ALL-UNNAMED,将读取所有未命名\n 模块。\n --add-exports /=(,)*\n 更新 以将 导出到 ,\n 而无论模块如何声明。\n 可以是 ALL-UNNAMED,将导出到所有\n 未命名模块。\n --add-opens /=(,)*\n 更新 以在 中打开\n ,而无论模块如何声明。\n --limit-modules [,...]\n 限制可观察模块的领域\n --patch-module =({0})*\n 使用 JAR 文件或目录中的类和资源\n 覆盖或增强模块。\n --source \n 设置源文件模式中源的版本。\n --finalization=\n 控制 JVM 是否执行对象最终处理,\n 其中 为 "enabled" 或 "disabled" 之一。\n 默认情况下,最终处理处于启用状态。\n --sun-misc-unsafe-memory-access=\n 允许或拒绝使用不受支持的 API sun.misc.Unsafe\n 为 "allow"、"warn"、"debug" 或 "deny" 之一。\n 默认值为 "warn"。\n\n这些额外选项如有更改, 恕不另行通知。\n # Translators please note do not translate the options themselves java.launcher.X.macosx.usage=\n以下选项是特定于 macOS 的选项:\n -XstartOnFirstThread\n 在第一个 (AppKit) 线程上运行 main() 方法\n -Xdock:name=\n 覆盖停靠栏中显示的默认应用程序名称\n -Xdock:icon=\n 覆盖停靠栏中显示的默认图标\n\n +# Translators please note do not translate the options themselves +java.launcher.opt.concise.header = 用法:java [java options...] [application arguments...]\n\n其中, 为以下项之一:\n 执行编译的主类的 main 方法\n -jar .jar 执行 JAR 档案的主类\n -m [/] 执行模块的主类\n .java 编译和执行源文件程序\n\n其中,主要的 java 选项包括:\n --class-path \n 其中, 是用于搜索类文件的目录和 JAR 档案列表(以 "{0}" 分隔)\n --module-path \n 其中, 是用于搜索模块的目录和 JAR 档案列表(以 "{0}" 分隔)\n -version\n 将产品版本输出到错误流并退出\n\n获取有关用法的其他帮助: java --help\n获取交互式 Java 环境: jshell + java.launcher.bad.option=\n无法识别的 showSettings 选项:{0}\n有效值为 "all"、"locale"、"properties"、"security"、"system"(仅 Linux)、"vm"\n有效的 "security" 子选项值为 "all"、"properties"、"providers"、"tls"\n请参见 "java -X"\n java.launcher.cls.error1=错误: 找不到或无法加载主类 {0}\n原因: {1}: {2} java.launcher.cls.error2=错误: 在类 {0} 中找不到 main 方法, 请将 main 方法定义为:\n public static void main(String[] args)\n否则 JavaFX 应用程序类必须扩展{1} diff --git a/src/java.base/share/classes/sun/security/provider/HSS.java b/src/java.base/share/classes/sun/security/provider/HSS.java index cb7d470b480..c1cb5ed6a30 100644 --- a/src/java.base/share/classes/sun/security/provider/HSS.java +++ b/src/java.base/share/classes/sun/security/provider/HSS.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -757,12 +757,8 @@ static class HSSPublicKey extends X509Key implements Serializable { Arrays.copyOfRange(keyArray, 4, keyArray.length), 0, true); algid = new AlgorithmId(ObjectIdentifier.of(KnownOIDs.HSSLMS)); - byte[] derEncodedKeyarray = - new DerOutputStream() - .putOctetString(keyArray) - .toByteArray(); this.setKey(new BitArray( - 8 * derEncodedKeyarray.length, derEncodedKeyarray)); + 8 * keyArray.length, keyArray)); } } @@ -783,11 +779,17 @@ public String toString() { @Override protected void parseKeyBits() throws InvalidKeyException { byte[] keyArray = getKey().toByteArray(); - if ((keyArray[0] != DerValue.tag_OctetString) || (keyArray[1] != keyArray.length -2)) { - throw new InvalidKeyException("Bad X509Key"); + if (keyArray.length < 12) { // More length check in LMSPublicKey + throw new InvalidKeyException("LMS public key is too short"); + } + if (keyArray[0] == DerValue.tag_OctetString + && keyArray[1] == keyArray.length - 2) { + // pre-8347596 format that has an inner OCTET STRING. + keyArray = Arrays.copyOfRange(keyArray, 2, keyArray.length); + setKey(new BitArray(keyArray.length * 8, keyArray)); } - L = LMSUtils.fourBytesToInt(keyArray, 2); - lmsPublicKey = new LMSPublicKey(keyArray, 6, true); + L = LMSUtils.fourBytesToInt(keyArray, 0); + lmsPublicKey = new LMSPublicKey(keyArray, 4, true); } @java.io.Serial diff --git a/src/java.base/share/classes/sun/security/tools/keytool/Main.java b/src/java.base/share/classes/sun/security/tools/keytool/Main.java index e10b05eceae..71374601eb2 100644 --- a/src/java.base/share/classes/sun/security/tools/keytool/Main.java +++ b/src/java.base/share/classes/sun/security/tools/keytool/Main.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,8 +39,8 @@ import java.security.cert.CertificateException; import java.security.cert.TrustAnchor; import java.security.cert.URICertStoreParameters; - - +import java.security.spec.ECParameterSpec; +import java.security.spec.NamedParameterSpec; import java.text.Collator; import java.text.MessageFormat; import java.util.*; @@ -61,19 +61,12 @@ import sun.security.pkcs12.PKCS12KeyStore; import sun.security.provider.certpath.CertPathConstraintsParameters; -import sun.security.util.ConstraintsParameters; -import sun.security.util.ECKeySizeParameterSpec; -import sun.security.util.KeyUtil; -import sun.security.util.ObjectIdentifier; +import sun.security.util.*; import sun.security.pkcs10.PKCS10; import sun.security.pkcs10.PKCS10Attribute; import sun.security.provider.X509Factory; import sun.security.provider.certpath.ssl.SSLServerCertStore; -import sun.security.util.KnownOIDs; -import sun.security.util.Password; -import sun.security.util.SecurityProperties; -import sun.security.util.SecurityProviderConstants; -import sun.security.util.SignatureUtil; + import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; @@ -82,15 +75,12 @@ import sun.security.pkcs.PKCS9Attribute; import sun.security.tools.KeyStoreUtil; import sun.security.tools.PathList; -import sun.security.util.DerValue; -import sun.security.util.Pem; import sun.security.validator.Validator; import sun.security.x509.*; import static java.security.KeyStore.*; import static sun.security.tools.keytool.Main.Command.*; import static sun.security.tools.keytool.Main.Option.*; -import sun.security.util.DisabledAlgorithmConstraints; /** * This tool manages keystores. @@ -2035,20 +2025,18 @@ private void doGenKeyPair(String alias, String dname, String keyAlgName, Object[] source; if (signerAlias != null) { form = new MessageFormat(rb.getString - ("Generating.keysize.bit.keyAlgName.key.pair.and.a.certificate.sigAlgName.issued.by.signerAlias.with.a.validity.of.validality.days.for")); + ("Generating.full.keyAlgName.key.pair.and.a.certificate.sigAlgName.issued.by.signerAlias.with.a.validity.of.days.for")); source = new Object[]{ - groupName == null ? keysize : KeyUtil.getKeySize(privKey), - KeyUtil.fullDisplayAlgName(privKey), + fullDisplayKeyName(privKey), newCert.getSigAlgName(), signerAlias, validity, x500Name}; } else { form = new MessageFormat(rb.getString - ("Generating.keysize.bit.keyAlgName.key.pair.and.self.signed.certificate.sigAlgName.with.a.validity.of.validality.days.for")); + ("Generating.full.keyAlgName.key.pair.and.self.signed.certificate.sigAlgName.with.a.validity.of.days.for")); source = new Object[]{ - groupName == null ? keysize : KeyUtil.getKeySize(privKey), - KeyUtil.fullDisplayAlgName(privKey), + fullDisplayKeyName(privKey), newCert.getSigAlgName(), validity, x500Name}; @@ -2073,6 +2061,38 @@ private void doGenKeyPair(String alias, String dname, String keyAlgName, keyStore.setKeyEntry(alias, privKey, keyPass, finalChain); } + /** + * Returns the full display name of the given key object. Could be + * - "X25519", if its getParams() is NamedParameterSpec + * - "EC (secp256r1)", if it's an EC key + * - "1024-bit RSA", other known keys + * - plain algorithm name, otherwise + * + * Note: the same method appears in keytool and jarsigner which uses + * same resource string defined in their own Resources.java. + * + * @param key the key object, cannot be null + * @return the full name + */ + private static String fullDisplayKeyName(Key key) { + var alg = key.getAlgorithm(); + if (key instanceof AsymmetricKey ak) { + var params = ak.getParams(); + if (params instanceof NamedParameterSpec nps) { + return nps.getName(); // directly return + } else if (params instanceof ECParameterSpec eps) { + var nc = CurveDB.lookup(eps); + if (nc != null) { + alg += " (" + nc.getNameAndAliases()[0] + ")"; // append name + } + } + } + var size = KeyUtil.getKeySize(key); + return size >= 0 + ? String.format(rb.getString("size.bit.alg"), size, alg) + : alg; + } + private String ecGroupNameForSize(int size) throws Exception { AlgorithmParameters ap = AlgorithmParameters.getInstance("EC"); ap.init(new ECKeySizeParameterSpec(size)); @@ -3598,22 +3618,17 @@ private String withWeak(String alg) { private String withWeakConstraint(Key key, CertPathConstraintsParameters cpcp) { - int kLen = KeyUtil.getKeySize(key); - String displayAlg = KeyUtil.fullDisplayAlgName(key); + String displayAlg = fullDisplayKeyName(key); try { DISABLED_CHECK.permits(key.getAlgorithm(), cpcp, true); } catch (CertPathValidatorException e) { - return String.format(rb.getString("key.bit.disabled"), kLen, displayAlg); + return String.format(rb.getString("key.bit.disabled"), displayAlg); } try { LEGACY_CHECK.permits(key.getAlgorithm(), cpcp, true); - if (kLen >= 0) { - return String.format(rb.getString("key.bit"), kLen, displayAlg); - } else { - return String.format(rb.getString("unknown.size.1"), displayAlg); - } + return String.format(rb.getString("key.bit"), displayAlg); } catch (CertPathValidatorException e) { - return String.format(rb.getString("key.bit.weak"), kLen, displayAlg); + return String.format(rb.getString("key.bit.weak"), displayAlg); } } @@ -4977,14 +4992,12 @@ private void checkWeakConstraint(String label, String sigAlg, Key key, } catch (CertPathValidatorException e) { weakWarnings.add(String.format( rb.getString("whose.key.weak"), label, - String.format(rb.getString("key.bit"), - KeyUtil.getKeySize(key), KeyUtil.fullDisplayAlgName(key)))); + String.format(rb.getString("key.bit"), fullDisplayKeyName(key)))); } } catch (CertPathValidatorException e) { weakWarnings.add(String.format( rb.getString("whose.key.disabled"), label, - String.format(rb.getString("key.bit"), - KeyUtil.getKeySize(key), KeyUtil.fullDisplayAlgName(key)))); + String.format(rb.getString("key.bit"), fullDisplayKeyName(key)))); } } } @@ -5004,13 +5017,11 @@ private void checkWeak(String label, String sigAlg, Key key) { if (!DISABLED_CHECK.permits(SIG_PRIMITIVE_SET, key)) { weakWarnings.add(String.format( rb.getString("whose.key.disabled"), label, - String.format(rb.getString("key.bit"), - KeyUtil.getKeySize(key), KeyUtil.fullDisplayAlgName(key)))); + String.format(rb.getString("key.bit"), fullDisplayKeyName(key)))); } else if (!LEGACY_CHECK.permits(SIG_PRIMITIVE_SET, key)) { weakWarnings.add(String.format( rb.getString("whose.key.weak"), label, - String.format(rb.getString("key.bit"), - KeyUtil.getKeySize(key), KeyUtil.fullDisplayAlgName(key)))); + String.format(rb.getString("key.bit"), fullDisplayKeyName(key)))); } } } @@ -5075,7 +5086,7 @@ private void checkWeakConstraint(String label, SecretKey secKey, weakWarnings.add(String.format( rb.getString("key.size.weak"), label, String.format(rb.getString("key.bit"), - KeyUtil.getKeySize(secKey), secKeyAlg))); + fullDisplayKeyName(secKey)))); } else { weakWarnings.add(String.format( rb.getString("key.algorithm.weak"), label, secKeyAlg)); diff --git a/src/java.base/share/classes/sun/security/tools/keytool/Resources.java b/src/java.base/share/classes/sun/security/tools/keytool/Resources.java index 3865c97dd85..9fc4d43f677 100644 --- a/src/java.base/share/classes/sun/security/tools/keytool/Resources.java +++ b/src/java.base/share/classes/sun/security/tools/keytool/Resources.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -307,10 +307,12 @@ public class Resources extends java.util.ListResourceBundle { "Specifying -keysize for generating EC keys is deprecated, please use \"-groupname %s\" instead."}, {"Key.pair.not.generated.alias.alias.already.exists", "Key pair not generated, alias <{0}> already exists"}, - {"Generating.keysize.bit.keyAlgName.key.pair.and.self.signed.certificate.sigAlgName.with.a.validity.of.validality.days.for", - "Generating {0} bit {1} key pair and self-signed certificate ({2}) with a validity of {3} days\n\tfor: {4}"}, - {"Generating.keysize.bit.keyAlgName.key.pair.and.a.certificate.sigAlgName.issued.by.signerAlias.with.a.validity.of.validality.days.for", - "Generating {0} bit {1} key pair and a certificate ({2}) issued by <{3}> with a validity of {4} days\n\tfor: {5}"}, + {"size.bit.alg", + "%1$d-bit %2$s"}, + {"Generating.full.keyAlgName.key.pair.and.self.signed.certificate.sigAlgName.with.a.validity.of.days.for", + "Generating {0} key pair and self-signed certificate ({1}) with a validity of {2} days\n\tfor: {3}"}, + {"Generating.full.keyAlgName.key.pair.and.a.certificate.sigAlgName.issued.by.signerAlias.with.a.validity.of.days.for", + "Generating {0} key pair and a certificate ({1}) issued by <{2}> with a validity of {3} days\n\tfor: {4}"}, {"Enter.key.password.for.alias.", "Enter key password for <{0}>"}, {".RETURN.if.same.as.keystore.password.", "\t(RETURN if same as keystore password): "}, @@ -479,10 +481,9 @@ public class Resources extends java.util.ListResourceBundle { {"alias.in.keystore", "Issuer <%s>"}, {"with.weak", "%s (weak)"}, {"with.disabled", "%s (disabled)"}, - {"key.bit", "%1$d-bit %2$s key"}, - {"key.bit.weak", "%1$d-bit %2$s key (weak)"}, - {"key.bit.disabled", "%1$d-bit %2$s key (disabled)"}, - {"unknown.size.1", "%s key of unknown size"}, + {"key.bit", "%s key"}, + {"key.bit.weak", "%s key (weak)"}, + {"key.bit.disabled", "%s key (disabled)"}, {".PATTERN.printX509Cert.with.weak", "Owner: {0}\nIssuer: {1}\nSerial number: {2}\nValid from: {3} until: {4}\nCertificate fingerprints:\n\t SHA1: {5}\n\t SHA256: {6}\nSignature algorithm name: {7}\nSubject Public Key Algorithm: {8}\nVersion: {9}"}, {"PKCS.10.with.weak", @@ -494,7 +495,7 @@ public class Resources extends java.util.ListResourceBundle { {"Unable.to.parse.denyAfter.string.in.exception.message", "Unable to parse denyAfter date string in exception message"}, {"whose.sigalg.weak", "%1$s uses the %2$s signature algorithm which is considered a security risk."}, {"whose.key.disabled", "%1$s uses a %2$s which is considered a security risk and is disabled."}, - {"whose.key.weak", "%1$s uses a %2$s which is considered a security risk. This key size will be disabled in a future update."}, + {"whose.key.weak", "%1$s uses a %2$s which is considered a security risk. It will be disabled in a future update."}, {"jks.storetype.warning", "The %1$s keystore uses a proprietary format. It is recommended to migrate to PKCS12 which is an industry standard format using \"keytool -importkeystore -srckeystore %2$s -destkeystore %2$s -deststoretype pkcs12\"."}, {"migrate.keystore.warning", "Migrated \"%1$s\" to %4$s. The %2$s keystore is backed up as \"%3$s\"."}, {"backup.keystore.warning", "The original keystore \"%1$s\" is backed up as \"%3$s\"..."}, diff --git a/src/java.base/share/classes/sun/security/util/KeyUtil.java b/src/java.base/share/classes/sun/security/util/KeyUtil.java index d057bb689e9..6eb5acfade3 100644 --- a/src/java.base/share/classes/sun/security/util/KeyUtil.java +++ b/src/java.base/share/classes/sun/security/util/KeyUtil.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -174,27 +174,6 @@ public static final int getKeySize(AlgorithmParameters parameters) { return -1; } - /** - * Returns the algorithm name of the given key object. If an EC key is - * specified, returns the algorithm name and its named curve. - * - * @param key the key object, cannot be null - * @return the algorithm name of the given key object, or return in the - * form of "EC (named curve)" if the given key object is an EC key - */ - public static final String fullDisplayAlgName(Key key) { - String result = key.getAlgorithm(); - if (key instanceof AsymmetricKey ak) { - AlgorithmParameterSpec paramSpec = ak.getParams(); - if (paramSpec instanceof NamedCurve nc) { - result += " (" + nc.getNameAndAliases()[0] + ")"; - } else if (paramSpec instanceof NamedParameterSpec nps) { - result = nps.getName(); - } - } - return result; - } - /** * Returns whether the key is valid or not. *

@@ -424,7 +403,7 @@ public static String hashAlgFromHSS(PublicKey publicKey) try { DerValue val = new DerValue(publicKey.getEncoded()); val.data.getDerValue(); - byte[] rawKey = new DerValue(val.data.getBitString()).getOctetString(); + byte[] rawKey = val.data.getBitString(); // According to https://www.rfc-editor.org/rfc/rfc8554.html: // Section 6.1: HSS public key is u32str(L) || pub[0], where pub[0] // is the LMS public key for the top-level tree. diff --git a/src/java.base/share/classes/sun/security/util/Resources_de.java b/src/java.base/share/classes/sun/security/util/Resources_de.java index 57e2c8da863..0ff218d6390 100644 --- a/src/java.base/share/classes/sun/security/util/Resources_de.java +++ b/src/java.base/share/classes/sun/security/util/Resources_de.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -59,8 +59,6 @@ public class Resources_de extends java.util.ListResourceBundle { // javax.security.auth.Subject {"NEWLINE", "\n"}, - {"invalid.null.AccessControlContext.provided", - "Ung\u00FCltiger Nullwert f\u00FCr AccessControlContext angegeben"}, {"invalid.null.action.provided", "Ung\u00FCltige Nullaktion angegeben"}, {"invalid.null.Class.provided", "Ung\u00FCltige Nullklasse angegeben"}, {"Subject.", "Subjekt:\n"}, @@ -90,40 +88,9 @@ public class Resources_de extends java.util.ListResourceBundle { {"Login.Failure.all.modules.ignored", "Anmeldefehler: Alle Module werden ignoriert"}, - // sun.security.provider.PolicyFile - - {"java.security.policy.error.parsing.policy.message", - "java.security.policy: Fehler beim Parsen von {0}:\n\t{1}"}, - {"java.security.policy.error.adding.Permission.perm.message", - "java.security.policy: Fehler beim Hinzuf\u00FCgen von Berechtigung, {0}:\n\t{1}"}, - {"java.security.policy.error.adding.Entry.message", - "java.security.policy: Fehler beim Hinzuf\u00FCgen von Eintrag:\n\t{0}"}, - {"alias.name.not.provided.pe.name.", "Aliasname nicht angegeben ({0})"}, - {"unable.to.perform.substitution.on.alias.suffix", - "Substitution f\u00FCr Alias {0} kann nicht ausgef\u00FChrt werden"}, - {"substitution.value.prefix.unsupported", - "Substitutionswert {0} nicht unterst\u00FCtzt"}, - {"SPACE", " "}, - {"LPARAM", "("}, - {"RPARAM", ")"}, - {"type.can.t.be.null","Typ kann nicht null sein"}, - // sun.security.provider.PolicyParser - {"keystorePasswordURL.can.not.be.specified.without.also.specifying.keystore", - "keystorePasswordURL kann nicht ohne Keystore angegeben werden"}, - {"expected.keystore.type", "Keystore-Typ erwartet"}, - {"expected.keystore.provider", "Keystore-Provider erwartet"}, - {"multiple.Codebase.expressions", - "mehrere Codebase-Ausdr\u00FCcke"}, - {"multiple.SignedBy.expressions","mehrere SignedBy-Ausdr\u00FCcke"}, {"duplicate.keystore.domain.name","Keystore-Domainname doppelt vorhanden: {0}"}, {"duplicate.keystore.name","Keystore-Name doppelt vorhanden: {0}"}, - {"SignedBy.has.empty.alias","Leerer Alias in SignedBy"}, - {"can.not.specify.Principal.with.a.wildcard.class.without.a.wildcard.name", - "Principal kann nicht mit einer Platzhalterklasse ohne Platzhalternamen angegeben werden"}, - {"expected.codeBase.or.SignedBy.or.Principal", - "codeBase oder SignedBy oder Principal erwartet"}, - {"expected.permission.entry", "Berechtigungseintrag erwartet"}, {"number.", "Nummer "}, {"expected.expect.read.end.of.file.", "[{0}] erwartet, [Dateiende] gelesen"}, @@ -132,8 +99,6 @@ public class Resources_de extends java.util.ListResourceBundle { {"line.number.msg", "Zeile {0}: {1}"}, {"line.number.expected.expect.found.actual.", "Zeile {0}: [{1}] erwartet, [{2}] gefunden"}, - {"null.principalClass.or.principalName", - "principalClass oder principalName null"}, // sun.security.pkcs11.SunPKCS11 {"PKCS11.Token.providerName.Password.", diff --git a/src/java.base/share/classes/sun/security/util/Resources_ja.java b/src/java.base/share/classes/sun/security/util/Resources_ja.java index 1293a48aabc..3cf3b91a62a 100644 --- a/src/java.base/share/classes/sun/security/util/Resources_ja.java +++ b/src/java.base/share/classes/sun/security/util/Resources_ja.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -59,8 +59,6 @@ public class Resources_ja extends java.util.ListResourceBundle { // javax.security.auth.Subject {"NEWLINE", "\n"}, - {"invalid.null.AccessControlContext.provided", - "\u7121\u52B9\u306Anull AccessControlContext\u304C\u6307\u5B9A\u3055\u308C\u307E\u3057\u305F"}, {"invalid.null.action.provided", "\u7121\u52B9\u306Anull\u30A2\u30AF\u30B7\u30E7\u30F3\u304C\u6307\u5B9A\u3055\u308C\u307E\u3057\u305F"}, {"invalid.null.Class.provided", "\u7121\u52B9\u306Anull\u30AF\u30E9\u30B9\u304C\u6307\u5B9A\u3055\u308C\u307E\u3057\u305F"}, {"Subject.", "\u30B5\u30D6\u30B8\u30A7\u30AF\u30C8:\n"}, @@ -90,40 +88,9 @@ public class Resources_ja extends java.util.ListResourceBundle { {"Login.Failure.all.modules.ignored", "\u30ED\u30B0\u30A4\u30F3\u5931\u6557: \u3059\u3079\u3066\u306E\u30E2\u30B8\u30E5\u30FC\u30EB\u306F\u7121\u8996\u3055\u308C\u307E\u3059"}, - // sun.security.provider.PolicyFile - - {"java.security.policy.error.parsing.policy.message", - "java.security.policy: {0}\u306E\u69CB\u6587\u89E3\u6790\u30A8\u30E9\u30FC:\n\t{1}"}, - {"java.security.policy.error.adding.Permission.perm.message", - "java.security.policy: \u30A2\u30AF\u30BB\u30B9\u6A29{0}\u306E\u8FFD\u52A0\u30A8\u30E9\u30FC:\n\t{1}"}, - {"java.security.policy.error.adding.Entry.message", - "java.security.policy: \u30A8\u30F3\u30C8\u30EA\u306E\u8FFD\u52A0\u30A8\u30E9\u30FC:\n\t{0}"}, - {"alias.name.not.provided.pe.name.", "\u5225\u540D\u306E\u6307\u5B9A\u304C\u3042\u308A\u307E\u305B\u3093({0})"}, - {"unable.to.perform.substitution.on.alias.suffix", - "\u5225\u540D{0}\u306B\u5BFE\u3057\u3066\u7F6E\u63DB\u64CD\u4F5C\u304C\u3067\u304D\u307E\u305B\u3093"}, - {"substitution.value.prefix.unsupported", - "\u7F6E\u63DB\u5024{0}\u306F\u30B5\u30DD\u30FC\u30C8\u3055\u308C\u3066\u3044\u307E\u305B\u3093"}, - {"SPACE", " "}, - {"LPARAM", "("}, - {"RPARAM", ")"}, - {"type.can.t.be.null","\u5165\u529B\u3092null\u306B\u3059\u308B\u3053\u3068\u306F\u3067\u304D\u307E\u305B\u3093"}, - // sun.security.provider.PolicyParser - {"keystorePasswordURL.can.not.be.specified.without.also.specifying.keystore", - "\u30AD\u30FC\u30B9\u30C8\u30A2\u3092\u6307\u5B9A\u3057\u306A\u3044\u5834\u5408\u3001keystorePasswordURL\u306F\u6307\u5B9A\u3067\u304D\u307E\u305B\u3093"}, - {"expected.keystore.type", "\u4E88\u60F3\u3055\u308C\u305F\u30AD\u30FC\u30B9\u30C8\u30A2\u30FB\u30BF\u30A4\u30D7"}, - {"expected.keystore.provider", "\u4E88\u60F3\u3055\u308C\u305F\u30AD\u30FC\u30B9\u30C8\u30A2\u30FB\u30D7\u30ED\u30D0\u30A4\u30C0"}, - {"multiple.Codebase.expressions", - "\u8907\u6570\u306ECodebase\u5F0F"}, - {"multiple.SignedBy.expressions","\u8907\u6570\u306ESignedBy\u5F0F"}, {"duplicate.keystore.domain.name","\u91CD\u8907\u3059\u308B\u30AD\u30FC\u30B9\u30C8\u30A2\u30FB\u30C9\u30E1\u30A4\u30F3\u540D: {0}"}, {"duplicate.keystore.name","\u91CD\u8907\u3059\u308B\u30AD\u30FC\u30B9\u30C8\u30A2\u540D: {0}"}, - {"SignedBy.has.empty.alias","SignedBy\u306F\u7A7A\u306E\u5225\u540D\u3092\u4FDD\u6301\u3057\u307E\u3059"}, - {"can.not.specify.Principal.with.a.wildcard.class.without.a.wildcard.name", - "\u30EF\u30A4\u30EB\u30C9\u30AB\u30FC\u30C9\u540D\u306E\u306A\u3044\u30EF\u30A4\u30EB\u30C9\u30AB\u30FC\u30C9\u30FB\u30AF\u30E9\u30B9\u3092\u4F7F\u7528\u3057\u3066\u3001\u30D7\u30EA\u30F3\u30B7\u30D1\u30EB\u3092\u6307\u5B9A\u3059\u308B\u3053\u3068\u306F\u3067\u304D\u307E\u305B\u3093"}, - {"expected.codeBase.or.SignedBy.or.Principal", - "\u4E88\u60F3\u3055\u308C\u305FcodeBase\u3001SignedBy\u307E\u305F\u306FPrincipal"}, - {"expected.permission.entry", "\u4E88\u60F3\u3055\u308C\u305F\u30A2\u30AF\u30BB\u30B9\u6A29\u30A8\u30F3\u30C8\u30EA"}, {"number.", "\u6570 "}, {"expected.expect.read.end.of.file.", "[{0}]\u3067\u306F\u306A\u304F[\u30D5\u30A1\u30A4\u30EB\u306E\u7D42\u308F\u308A]\u304C\u8AAD\u307F\u8FBC\u307E\u308C\u307E\u3057\u305F"}, @@ -132,8 +99,6 @@ public class Resources_ja extends java.util.ListResourceBundle { {"line.number.msg", "\u884C{0}: {1}"}, {"line.number.expected.expect.found.actual.", "\u884C{0}: [{1}]\u3067\u306F\u306A\u304F[{2}]\u304C\u691C\u51FA\u3055\u308C\u307E\u3057\u305F"}, - {"null.principalClass.or.principalName", - "null\u306EprincipalClass\u307E\u305F\u306FprincipalName"}, // sun.security.pkcs11.SunPKCS11 {"PKCS11.Token.providerName.Password.", diff --git a/src/java.base/share/classes/sun/security/util/Resources_zh_CN.java b/src/java.base/share/classes/sun/security/util/Resources_zh_CN.java index 5376ff5efd3..b4f8f7b49df 100644 --- a/src/java.base/share/classes/sun/security/util/Resources_zh_CN.java +++ b/src/java.base/share/classes/sun/security/util/Resources_zh_CN.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -59,8 +59,6 @@ public class Resources_zh_CN extends java.util.ListResourceBundle { // javax.security.auth.Subject {"NEWLINE", "\n"}, - {"invalid.null.AccessControlContext.provided", - "\u63D0\u4F9B\u4E86\u65E0\u6548\u7684\u7A7A AccessControlContext"}, {"invalid.null.action.provided", "\u63D0\u4F9B\u4E86\u65E0\u6548\u7684\u7A7A\u64CD\u4F5C"}, {"invalid.null.Class.provided", "\u63D0\u4F9B\u4E86\u65E0\u6548\u7684\u7A7A\u7C7B"}, {"Subject.", "\u4E3B\u4F53: \n"}, @@ -90,40 +88,9 @@ public class Resources_zh_CN extends java.util.ListResourceBundle { {"Login.Failure.all.modules.ignored", "\u767B\u5F55\u5931\u8D25: \u5FFD\u7565\u6240\u6709\u6A21\u5757"}, - // sun.security.provider.PolicyFile - - {"java.security.policy.error.parsing.policy.message", - "java.security.policy: \u89E3\u6790{0}\u65F6\u51FA\u9519:\n\t{1}"}, - {"java.security.policy.error.adding.Permission.perm.message", - "java.security.policy: \u6DFB\u52A0\u6743\u9650{0}\u65F6\u51FA\u9519:\n\t{1}"}, - {"java.security.policy.error.adding.Entry.message", - "java.security.policy: \u6DFB\u52A0\u6761\u76EE\u65F6\u51FA\u9519:\n\t{0}"}, - {"alias.name.not.provided.pe.name.", "\u672A\u63D0\u4F9B\u522B\u540D ({0})"}, - {"unable.to.perform.substitution.on.alias.suffix", - "\u65E0\u6CD5\u5728\u522B\u540D {0} \u4E0A\u6267\u884C\u66FF\u4EE3"}, - {"substitution.value.prefix.unsupported", - "\u66FF\u4EE3\u503C{0}\u4E0D\u53D7\u652F\u6301"}, - {"SPACE", " "}, - {"LPARAM", "("}, - {"RPARAM", ")"}, - {"type.can.t.be.null","\u7C7B\u578B\u4E0D\u80FD\u4E3A\u7A7A\u503C"}, - // sun.security.provider.PolicyParser - {"keystorePasswordURL.can.not.be.specified.without.also.specifying.keystore", - "\u4E0D\u6307\u5B9A\u5BC6\u94A5\u5E93\u65F6\u65E0\u6CD5\u6307\u5B9A keystorePasswordURL"}, - {"expected.keystore.type", "\u5E94\u4E3A\u5BC6\u94A5\u5E93\u7C7B\u578B"}, - {"expected.keystore.provider", "\u5E94\u4E3A\u5BC6\u94A5\u5E93\u63D0\u4F9B\u65B9"}, - {"multiple.Codebase.expressions", - "\u591A\u4E2A\u4EE3\u7801\u5E93\u8868\u8FBE\u5F0F"}, - {"multiple.SignedBy.expressions","\u591A\u4E2A SignedBy \u8868\u8FBE\u5F0F"}, {"duplicate.keystore.domain.name","\u5BC6\u94A5\u5E93\u57DF\u540D\u91CD\u590D: {0}"}, {"duplicate.keystore.name","\u5BC6\u94A5\u5E93\u540D\u79F0\u91CD\u590D: {0}"}, - {"SignedBy.has.empty.alias","SignedBy \u6709\u7A7A\u522B\u540D"}, - {"can.not.specify.Principal.with.a.wildcard.class.without.a.wildcard.name", - "\u6CA1\u6709\u901A\u914D\u7B26\u540D\u79F0, \u65E0\u6CD5\u4F7F\u7528\u901A\u914D\u7B26\u7C7B\u6307\u5B9A\u4E3B\u7528\u6237"}, - {"expected.codeBase.or.SignedBy.or.Principal", - "\u5E94\u4E3A codeBase, SignedBy \u6216\u4E3B\u7528\u6237"}, - {"expected.permission.entry", "\u5E94\u4E3A\u6743\u9650\u6761\u76EE"}, {"number.", "\u7F16\u53F7 "}, {"expected.expect.read.end.of.file.", "\u5E94\u4E3A [{0}], \u8BFB\u53D6\u7684\u662F [\u6587\u4EF6\u7ED3\u5C3E]"}, @@ -132,8 +99,6 @@ public class Resources_zh_CN extends java.util.ListResourceBundle { {"line.number.msg", "\u5217{0}: {1}"}, {"line.number.expected.expect.found.actual.", "\u884C\u53F7 {0}: \u5E94\u4E3A [{1}], \u627E\u5230 [{2}]"}, - {"null.principalClass.or.principalName", - "principalClass \u6216 principalName \u4E3A\u7A7A\u503C"}, // sun.security.pkcs11.SunPKCS11 {"PKCS11.Token.providerName.Password.", diff --git a/src/java.base/share/man/java.md b/src/java.base/share/man/java.md index f6b7fd44917..9d1d6e266a3 100644 --- a/src/java.base/share/man/java.md +++ b/src/java.base/share/man/java.md @@ -1,5 +1,5 @@ --- -# Copyright (c) 1994, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1994, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -4002,11 +4002,40 @@ archive, you should make sure that the archive is created by at least version - The CDS archive cannot be loaded if any JAR files in the class path or module path are modified after the archive is generated. -- If any of the VM options `--upgrade-module-path`, `--patch-module` or - `--limit-modules` are specified, CDS is disabled. This means that the - JVM will execute without loading any CDS archives. In addition, if - you try to create a CDS archive with any of these 3 options specified, - the JVM will report an error. +### Module related options + +The following module related options are supported by CDS: `--module-path`, `--module`, +`--add-modules`, and `--enable-native-access`. + +The values for these options (if specified), should be identical when creating and using the +CDS archive. Otherwise, if there is a mismatch of any of these options, the CDS archive may be +partially or completely disabled, leading to lower performance. + +- If the -XX:+AOTClassLinking options *was* used during CDS archive creation, the CDS archive + cannot be used, and the following error message is printed: + + `CDS archive has aot-linked classes. It cannot be used when archived full module graph is not used` + +- If the -XX:+AOTClassLinking options *was not* used during CDS archive creation, the CDS archive + can be used, but the "archived module graph" feature will be disabled. This can lead to increased + start-up time. + +To diagnose problems with the above options, you can add `-Xlog:cds` to the application's VM +arguments. For example, if `--add-modules jdk.jconcole` was specified during archive creation +and `--add-modules jdk.incubator.vector` is specified during runtime, the following messages will +be logged: + + `Mismatched values for property jdk.module.addmods` + + `runtime jdk.incubator.vector dump time jdk.jconsole` + + `subgraph jdk.internal.module.ArchivedBootLayer cannot be used because full module graph is disabled` + +If any of the VM options `--upgrade-module-path`, `--patch-module` or +`--limit-modules` are specified, CDS is disabled. This means that the +JVM will execute without loading any CDS archives. In addition, if +you try to create a CDS archive with any of these 3 options specified, +the JVM will report an error. ## Performance Tuning Examples diff --git a/src/java.base/share/native/libjava/ub.h b/src/java.base/share/native/libjava/ub.h index cf7f491ca45..d6e0cac3bea 100644 --- a/src/java.base/share/native/libjava/ub.h +++ b/src/java.base/share/native/libjava/ub.h @@ -5,7 +5,9 @@ * * 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. + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or diff --git a/src/java.base/windows/classes/java/lang/ProcessImpl.java b/src/java.base/windows/classes/java/lang/ProcessImpl.java index 967693dcbc3..7f7c1e75013 100644 --- a/src/java.base/windows/classes/java/lang/ProcessImpl.java +++ b/src/java.base/windows/classes/java/lang/ProcessImpl.java @@ -204,13 +204,14 @@ private static String[] getTokensFromCommand(String command) { private static final int VERIFICATION_LEGACY = 3; // See Command shell overview for documentation of special characters. // https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-xp/bb490954(v=technet.10) - private static final char ESCAPE_VERIFICATION[][] = { + private static final String ESCAPE_VERIFICATION[] = { // We guarantee the only command file execution for implicit [cmd.exe] run. // http://technet.microsoft.com/en-us/library/bb490954.aspx - {' ', '\t', '\"', '<', '>', '&', '|', '^'}, - {' ', '\t', '\"', '<', '>'}, - {' ', '\t', '\"', '<', '>'}, - {' ', '\t'} + // All space characters require quoting are checked in needsEscaping(). + "\"<>&|^", + "\"<>", + "\"<>", + "" }; private static String createCommandLine(int verificationType, @@ -325,9 +326,14 @@ private static boolean needsEscaping(int verificationType, String arg) { } if (!argIsQuoted) { - char testEscape[] = ESCAPE_VERIFICATION[verificationType]; - for (int i = 0; i < testEscape.length; ++i) { - if (arg.indexOf(testEscape[i]) >= 0) { + for (int i = 0; i < arg.length(); i++) { + char ch = arg.charAt(i); + if (Character.isLetterOrDigit(ch)) + continue; // skip over common characters + // All space chars require quotes and other mode specific characters + if (Character.isSpaceChar(ch) || + Character.isWhitespace(ch) || + ESCAPE_VERIFICATION[verificationType].indexOf(ch) >= 0) { return true; } } diff --git a/src/java.desktop/share/classes/javax/print/attribute/standard/PresentationDirection.java b/src/java.desktop/share/classes/javax/print/attribute/standard/PresentationDirection.java index a9c971d82d6..d4ff8581a2d 100644 --- a/src/java.desktop/share/classes/javax/print/attribute/standard/PresentationDirection.java +++ b/src/java.desktop/share/classes/javax/print/attribute/standard/PresentationDirection.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,7 +43,7 @@ *

* IPP Compatibility: This attribute is not an IPP 1.1 attribute; it is * an attribute in the Production Printing Extension - * ( + * ( * PDF) of IPP 1.1. The category name returned by {@code getName()} is the * IPP attribute name. The enumeration's integer value is the IPP enum value. * The {@code toString()} method returns the IPP string representation of the diff --git a/src/java.desktop/share/native/libawt/java2d/SurfaceData.h b/src/java.desktop/share/native/libawt/java2d/SurfaceData.h index 8975f8d4a9d..f7124961392 100644 --- a/src/java.desktop/share/native/libawt/java2d/SurfaceData.h +++ b/src/java.desktop/share/native/libawt/java2d/SurfaceData.h @@ -60,7 +60,7 @@ typedef struct { #define UNSAFE_TO_SUB(a, b) \ (((b >= 0) && (a < 0) && (a < (INT_MIN + b))) || \ - ((b < 0) && (a >= 0) && (-b > (INT_MAX - a)))) \ + ((b < 0) && (a >= 0) && (a > (INT_MAX + b)))) \ /* * The SurfaceDataRasInfo structure is used to pass in and return various diff --git a/src/java.se/share/classes/module-info.java b/src/java.se/share/classes/module-info.java index 9a2704660b7..5dbf65830e3 100644 --- a/src/java.se/share/classes/module-info.java +++ b/src/java.se/share/classes/module-info.java @@ -23,8 +23,6 @@ * questions. */ -import jdk.internal.javac.ParticipatesInPreview; - /** * Defines the API of the Java SE Platform. * @@ -40,7 +38,6 @@ * @moduleGraph * @since 9 */ -@ParticipatesInPreview module java.se { requires transitive java.base; requires transitive java.compiler; diff --git a/src/java.sql/share/classes/java/sql/SQLPermission.java b/src/java.sql/share/classes/java/sql/SQLPermission.java index 863037502e5..84e41c51a33 100644 --- a/src/java.sql/share/classes/java/sql/SQLPermission.java +++ b/src/java.sql/share/classes/java/sql/SQLPermission.java @@ -32,7 +32,7 @@ * A {@code SQLPermission} object contains * a name (also referred to as a "target name") but no actions * list; there is either a named permission or there is not. - * The target name is the name of the permission (see below). The + * The target name is the name of the permission. The * naming convention follows the hierarchical property naming convention. * In addition, an asterisk * may appear at the end of the name, following a ".", or by itself, to diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_de.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_de.properties index 9f24c42b110..85f0a3be3c7 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_de.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_de.properties @@ -315,8 +315,8 @@ # Implementation limits - EntityExpansionLimit=JAXP00010001: Der Parser hat mehr als {0} Entityerweiterungen in diesem Dokument gefunden. Dies ist der von JDK vorgeschriebene Grenzwert. - ElementAttributeLimit=JAXP00010002: Element "{0}" hat mehr als {1} Attribute. "{1}" ist der von JDK vorgeschriebene Grenzwert. + EntityExpansionLimit=JAXP00010001: Der Parser hat mehr als {0} Entityerweiterungen in diesem Dokument gefunden. Das ist der von "{1}" vorgeschriebene Grenzwert. + ElementAttributeLimit=JAXP00010002: Element "{0}" hat mehr als {1} Attribute. "{1}" ist der von "{2}" vorgeschriebene Grenzwert. MaxEntitySizeLimit=JAXP00010003: Die Länge von Entity "{0}" ist "{1}" und überschreitet den Grenzwert "{2}", der von "{3}" festgelegt wurde. TotalEntitySizeLimit=JAXP00010004: Die akkumulierte Größe von Entitys ist "{0}" und überschreitet den Grenzwert "{1}", der von "{2}" festgelegt wurde. MaxXMLNameLimit=JAXP00010005: Die Länge von Entity "{0}" ist "{1}" und überschreitet den Grenzwert "{2}", der von "{3}" festgelegt wurde. diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_ja.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_ja.properties index 00bced117f6..f3e7d51bb85 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_ja.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_ja.properties @@ -315,8 +315,8 @@ # Implementation limits - EntityExpansionLimit=JAXP00010001: パーサーによって、このドキュメント内で"{0}"を超えるエンティティ拡張が検出されました。これは、JDKによる制限です。 - ElementAttributeLimit=JAXP00010002: 要素"{0}"に"{1}"を超える属性が存在します。"{1}"は、JDKによる制限です。 + EntityExpansionLimit=JAXP00010001: パーサーによって、このドキュメント内で"{0}"を超えるエンティティ拡張が検出されました。これは、"{1}"による制限です。 + ElementAttributeLimit=JAXP00010002: 要素"{0}"に"{1}"を超える属性が存在します。"{1}"は、"{2}"で設定された制限です。 MaxEntitySizeLimit=JAXP00010003: エンティティ"{0}"の長さは"{1}"で、"{3}"で設定された制限"{2}"を超えています。 TotalEntitySizeLimit=JAXP00010004: エンティティの累積サイズ"{0}"は、"{2}"で設定された制限"{1}"を超えました。 MaxXMLNameLimit=JAXP00010005: エンティティ"{0}"の長さは"{1}"で、"{3}"で設定された制限"{2}"を超えています。 diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_zh_CN.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_zh_CN.properties index ffe36a06f35..e35bf7bf17f 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_zh_CN.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_zh_CN.properties @@ -315,8 +315,8 @@ # Implementation limits - EntityExpansionLimit=JAXP00010001: 解析器在此文档中遇到多个 "{0}" 实体扩展; 这是 JDK 施加的限制。 - ElementAttributeLimit=JAXP00010002: 元素 "{0}" 具有多个 "{1}" 属性, "{1}" 是 JDK 施加的限制。 + EntityExpansionLimit=JAXP00010001:解析器在此文档中遇到多个 "{0}" 实体扩展;这是 "{1}" 施加的限制。 + ElementAttributeLimit=JAXP00010002:元素 "{0}" 具有多个 "{1}" 属性,"{1}" 是 "{2}" 设置的限制。 MaxEntitySizeLimit=JAXP00010003: 实体 "{0}" 的长度为 "{1}", 超过了 "{3}" 设置的 "{2}" 限制。 TotalEntitySizeLimit=JAXP00010004: 实体的累计大小为 "{0}", 超过了 "{2}" 设置的 "{1}" 限制。 MaxXMLNameLimit=JAXP00010005: 实体 "{0}" 的长度为 "{1}", 超过了 "{3}" 设置的 "{2}" 限制。 diff --git a/src/jdk.accessibility/windows/classes/com/sun/java/accessibility/internal/AccessBridge.java b/src/jdk.accessibility/windows/classes/com/sun/java/accessibility/internal/AccessBridge.java index e6792b3ef10..021a13fceac 100644 --- a/src/jdk.accessibility/windows/classes/com/sun/java/accessibility/internal/AccessBridge.java +++ b/src/jdk.accessibility/windows/classes/com/sun/java/accessibility/internal/AccessBridge.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -3904,6 +3904,8 @@ private int controlCode(KeyStroke keyStroke) { return 0; int code = keyStroke.getKeyCode(); switch (code) { + case KeyEvent.VK_TAB: + case KeyEvent.VK_SPACE: case KeyEvent.VK_BACK_SPACE: case KeyEvent.VK_DELETE: case KeyEvent.VK_DOWN: @@ -3946,15 +3948,10 @@ private char getKeyChar(KeyStroke keyStroke) { debugString("[INFO]: Shortcut is control character: " + Integer.toHexString(keyCode)); return (char)keyCode; } - String keyText = KeyEvent.getKeyText(keyStroke.getKeyCode()); - debugString("[INFO]: Shortcut is: " + keyText); - if (keyText != null || keyText.length() > 0) { - CharSequence seq = keyText.subSequence(0, 1); - if (seq != null || seq.length() > 0) { - return seq.charAt(0); - } - } - return 0; + + keyCode = keyStroke.getKeyCode(); + debugString("[INFO]: Shortcut is: " + Integer.toHexString(keyCode)); + return (char)keyCode; } /* diff --git a/src/jdk.accessibility/windows/native/include/bridge/AccessBridgePackages.h b/src/jdk.accessibility/windows/native/include/bridge/AccessBridgePackages.h index 27c31be09a8..232cab4b21b 100644 --- a/src/jdk.accessibility/windows/native/include/bridge/AccessBridgePackages.h +++ b/src/jdk.accessibility/windows/native/include/bridge/AccessBridgePackages.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1108,6 +1108,8 @@ typedef long ABHWND64; #define ACCESSIBLE_CONTROLCODE_KEYSTROKE 512 // Control code key pressed, character contains control code. // The supported control code keys are: +#define ACCESSIBLE_VK_TAB 9 +#define ACCESSIBLE_VK_SPACE 32 #define ACCESSIBLE_VK_BACK_SPACE 8 #define ACCESSIBLE_VK_DELETE 127 #define ACCESSIBLE_VK_DOWN 40 diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Directive.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Directive.java index cf942dab5cd..f41866ddb6a 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Directive.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Directive.java @@ -76,7 +76,7 @@ public static int value(Set s) { @Override public String toString() { - return String.format("ACC_%s (0x%04x", name(), value); + return String.format("ACC_%s (0x%04x)", name(), value); } } diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Preview.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Preview.java index c66e1758616..3879f72ff30 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Preview.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Preview.java @@ -150,7 +150,9 @@ public boolean participatesInPreview(Symtab syms, ModuleSymbol m) { // s participates in the preview API return syms.java_base.exports.stream() .filter(ed -> ed.packge.fullname == names.jdk_internal_javac) - .anyMatch(ed -> ed.modules.contains(m)); + .anyMatch(ed -> ed.modules.contains(m)) || + //the specification lists the java.se module as participating in preview: + m.name == names.java_se; } /** diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java index 62f7c15a95f..2c3a79650b4 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java @@ -2587,10 +2587,6 @@ public void visitApply(JCMethodInvocation tree) { chk.checkRefType(qualifier.pos(), attribExpr(qualifier, localEnv, encl)); - } else if (methName == names._super) { - // qualifier omitted; check for existence - // of an appropriate implicit qualifier. - checkNewInnerClass(tree.meth.pos(), localEnv, site, true); } } else if (tree.meth.hasTag(SELECT)) { log.error(tree.meth.pos(), @@ -2598,6 +2594,15 @@ public void visitApply(JCMethodInvocation tree) { attribExpr(((JCFieldAccess) tree.meth).selected, localEnv, site); } + if (tree.meth.hasTag(IDENT)) { + // non-qualified super(...) call; check whether explicit constructor + // invocation is well-formed. If the super class is an inner class, + // make sure that an appropriate implicit qualifier exists. If the super + // class is a local class, make sure that the current class is defined + // in the same context as the local class. + checkNewInnerClass(tree.meth.pos(), localEnv, site, true); + } + // if we're calling a java.lang.Enum constructor, // prefix the implicit String and int parameters if (site.tsym == syms.enumSym) @@ -3065,7 +3070,7 @@ public void report(DiagnosticPosition _unused, JCDiagnostic details) { } void checkNewInnerClass(DiagnosticPosition pos, Env env, Type type, boolean isSuper) { - boolean isLocal = type.tsym.owner.kind == MTH; + boolean isLocal = type.tsym.owner.kind == VAR || type.tsym.owner.kind == MTH; if ((type.tsym.flags() & (INTERFACE | ENUM | RECORD)) != 0 || (!isLocal && !type.tsym.isInner()) || (isSuper && env.enclClass.sym.isAnonymous())) { diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java index bfad334d194..96d633cac7f 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -103,7 +103,6 @@ import com.sun.tools.javac.tree.TreeInfo; import com.sun.tools.javac.util.Assert; import com.sun.tools.javac.util.Context; -import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.ListBuffer; @@ -151,7 +150,6 @@ public class Modules extends JCTree.Visitor { private final Target target; private final boolean allowModules; private final boolean allowAccessIntoSystem; - private final boolean allowRequiresTransitiveJavaBase; public final boolean multiModuleMode; @@ -207,11 +205,6 @@ protected Modules(Context context) { allowAccessIntoSystem = options.isUnset(Option.RELEASE); - Preview preview = Preview.instance(context); - - allowRequiresTransitiveJavaBase = - Feature.JAVA_BASE_TRANSITIVE.allowedInSource(source) && - (!preview.isPreview(Feature.JAVA_BASE_TRANSITIVE) || preview.isEnabled()); lintOptions = options.isUnset(Option.XLINT_CUSTOM, "-" + LintCategory.OPTIONS.option); multiModuleMode = fileManager.hasLocation(StandardLocation.MODULE_SOURCE_PATH); @@ -822,12 +815,10 @@ public void visitRequires(JCRequires tree) { Set flags = EnumSet.noneOf(RequiresFlag.class); if (tree.isTransitive) { if (msym == syms.java_base && - !allowRequiresTransitiveJavaBase && !preview.participatesInPreview(syms, sym)) { if (source.compareTo(Source.JDK10) >= 0) { - log.error(DiagnosticFlag.SOURCE_LEVEL, - tree.pos(), - Feature.JAVA_BASE_TRANSITIVE.error(source.name)); + preview.checkSourceLevel(tree.pos(), + Feature.JAVA_BASE_TRANSITIVE); } } flags.add(RequiresFlag.TRANSITIVE); diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java index 43a0c61a069..855b8a4b234 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java @@ -3834,7 +3834,7 @@ Symbol findSelfContaining(DiagnosticPosition pos, */ Symbol findLocalClassOwner(Env env, TypeSymbol c) { Symbol owner = c.owner; - Assert.check(owner.kind == MTH); + Assert.check(owner.kind == MTH || owner.kind == VAR); Env env1 = env; boolean staticOnly = false; while (env1.outer != null) { @@ -3846,7 +3846,9 @@ Symbol findLocalClassOwner(Env env, TypeSymbol c) { if (isStatic(env1)) staticOnly = true; env1 = env1.outer; } - return methodNotFound; + return owner.kind == MTH ? + methodNotFound : + varNotFound; } /** diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties index 96944f698dd..36924d584be 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties @@ -3245,6 +3245,7 @@ compiler.misc.feature.flexible.constructors=\ compiler.misc.feature.module.imports=\ module imports +# L10N: do not localize: transitive compiler.misc.feature.java.base.transitive=\ transitive modifier for java.base @@ -3770,7 +3771,7 @@ compiler.misc.cant.resolve.modules=\ cannot resolve modules compiler.misc.bad.requires.flag=\ - bad requires flag: {0} + invalid flag for "requires java.base": {0} # 0: string compiler.err.invalid.module.specifier=\ diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_de.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_de.properties index 33063b6558d..130a644da94 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_de.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_de.properties @@ -635,6 +635,9 @@ compiler.err.limit.stack=Code erfordert zu viel Stack compiler.err.limit.string=Konstantenzeichenfolge zu lang +# 0: symbol +compiler.err.annotation.array.too.large=Annotationsarrayelement zu groß in "{0}" + # 0: string compiler.err.limit.string.overflow=UTF8-Darstellung für Zeichenfolge "{0}..." ist zu lang für den Konstantenpool @@ -656,9 +659,6 @@ compiler.misc.unexpected.ret.val=Unerwarteter Rückgabewert # 0: set of flag compiler.err.mod.not.allowed.here=Modifikator {0} hier nicht zulässig -# 0: name -compiler.err.modifier.not.allowed.here=Modifikator {0} hier nicht zulässig - compiler.err.intf.not.allowed.here=Schnittstelle hier nicht zulässig # 0: symbol, 1: symbol @@ -781,9 +781,6 @@ compiler.err.not.def.access.class.intf.cant.access.reason={1}.{0} in Package {2} # 0: symbol, 1: symbol, 2: symbol, 3: message segment compiler.misc.not.def.access.class.intf.cant.access.reason={1}.{0} in Package {2} ist nicht zugänglich\n({3}) -# 0: symbol, 1: list of type, 2: type -compiler.misc.cant.access.inner.cls.constr=Zugriff auf Konstruktor {0}({1}) nicht möglich\nEinschließende Instanz vom Typ {2} ist nicht im Geltungsbereich - # 0: symbol, 1: symbol compiler.err.not.def.public.cant.access={0} ist nicht öffentlich in {1}. Zugriff von externem Package nicht möglich @@ -1148,6 +1145,10 @@ compiler.err.file.sb.on.source.or.patch.path.for.module=Datei muss sich im Quell compiler.err.no.java.lang=Package java.lang kann in Plattformklassen nicht gefunden werden +compiler.err.statement.not.expected=Anweisungen werden außerhalb von Methoden und Initializern nicht erwartet + +compiler.err.class.method.or.field.expected=Klasse, Schnittstelle, Annotationstyp, Enumeration, Datensatz, Methode oder Feld erwartet + ##### # Fatal Errors @@ -1589,6 +1590,7 @@ compiler.warn.proc.duplicate.option.name=Doppelte unterstützte Option "{0}" von # 0: string, 1: string compiler.warn.proc.duplicate.supported.annotation=Doppelte unterstützte Annotationsschnittstelle "{0}" von Annotationsprozessor "{1}" zurückgegeben + # 0: string compiler.warn.proc.redundant.types.with.wildcard=Annotationsprozessor "{0}" unterstützt redundant sowohl "*" als auch andere Annotationsschnittstellen @@ -1671,6 +1673,9 @@ compiler.warn.annotation.method.not.found=Annotationsmethode "{1}()" kann nicht # 0: type, 1: name, 2: message segment compiler.warn.annotation.method.not.found.reason=Annotationsmethode "{1}()" kann nicht in Typ "{0}" gefunden werden: {2} +# 0: list of annotation, 1: symbol, 2: name, 3: message segment +compiler.err.cant.attach.type.annotations=Typannotationen {0} können nicht an {1}.{2} angehängt werden:\n{3} + # 0: file object, 1: symbol, 2: name compiler.warn.unknown.enum.constant=Unbekannte Enum-Konstante {1}.{2} @@ -1806,7 +1811,11 @@ compiler.misc.bad.enclosing.class=Ungültige einschließende Klasse für {0}: {1 # 0: symbol compiler.misc.bad.enclosing.method=Ungültiges einschließendes Methodenattribut für Klasse {0} -compiler.misc.bad.runtime.invisible.param.annotations=Ungültiges RuntimeInvisibleParameterAnnotations-Attribut: {0} +# 0: file name +compiler.warn.runtime.visible.invisible.param.annotations.mismatch=Die Längen der Parameter im RuntimeVisibleParameterAnnotations-Attribut und RuntimeInvisibleParameterAnnotations-Attribut in {0} stimmen nicht überein. Beide Attribute werden ignoriert + +# 0: file name +compiler.warn.runtime.invisible.parameter.annotations=Die Attribute RuntimeVisibleParameterAnnotations und RuntimeInvisibleParameterAnnotations in {0} können nicht den Parametern der Methode zugeordnet werden compiler.misc.bad.const.pool.tag=Ungültiges Konstantenpooltag: {0} @@ -2038,6 +2047,10 @@ compiler.err.abstract.cant.be.accessed.directly={0} {1} in {2} ist abstrakt und # 0: symbol kind, 1: symbol compiler.err.non-static.cant.be.ref={0} {1} ist nicht statisch und kann nicht aus einem statischen Kontext referenziert werden +## The first argument ({0}) is a "kindname". +# 0: symbol kind, 1: symbol +compiler.err.local.cant.be.inst.static={0} {1} ist lokal und kann nicht aus einem statischen Kontext instanziiert werden + # 0: symbol kind, 1: symbol compiler.misc.bad.static.method.in.unbound.lookup=Unerwartete statische {0} {1} in ungebundenem Lookup gefunden @@ -2286,6 +2299,9 @@ compiler.misc.feature.flexible.constructors=Flexible Konstruktoren compiler.misc.feature.module.imports=Modulimporte +# L10N: do not localize: transitive +compiler.misc.feature.java.base.transitive=transitive Modifikator für java.base + compiler.warn.underscore.as.identifier=Ab Release 9 ist "_" ein Schlüsselwort und kann nicht als ID verwendet werden compiler.err.underscore.as.identifier=Ab Release 9 ist "_" ein Schlüsselwort und kann nicht als ID verwendet werden diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_ja.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_ja.properties index 818b5fb7066..2c108edf692 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_ja.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_ja.properties @@ -635,6 +635,9 @@ compiler.err.limit.stack=コードが要求するスタックが多すぎます compiler.err.limit.string=定数文字列が長すぎます +# 0: symbol +compiler.err.annotation.array.too.large="{0}"の注釈配列要素が大きすぎます + # 0: string compiler.err.limit.string.overflow=文字列"{0}..."のUTF8表現が、定数プールに対して長すぎます @@ -656,9 +659,6 @@ compiler.misc.unexpected.ret.val=予期しない戻り値 # 0: set of flag compiler.err.mod.not.allowed.here=修飾子{0}をここで使用することはできません -# 0: name -compiler.err.modifier.not.allowed.here=修飾子{0}をここで使用することはできません - compiler.err.intf.not.allowed.here=ここではインタフェースは許可されません # 0: symbol, 1: symbol @@ -781,9 +781,6 @@ compiler.err.not.def.access.class.intf.cant.access.reason=パッケージ{2}の{ # 0: symbol, 1: symbol, 2: symbol, 3: message segment compiler.misc.not.def.access.class.intf.cant.access.reason=パッケージ{2}の{1}.{0}にはアクセスできません\n({3}) -# 0: symbol, 1: list of type, 2: type -compiler.misc.cant.access.inner.cls.constr=コンストラクタ{0}({1})にアクセスできません\n内部クラスを囲む型{2}のインスタンスがスコープ内にありません - # 0: symbol, 1: symbol compiler.err.not.def.public.cant.access={1}の{0}はpublicではありません。パッケージ外からはアクセスできません @@ -1148,6 +1145,10 @@ compiler.err.file.sb.on.source.or.patch.path.for.module=ファイルは、ソー compiler.err.no.java.lang=プラットフォーム・クラスでパッケージjava.langを検出できません +compiler.err.statement.not.expected=文はメソッドおよびイニシャライザの外では必要ありません + +compiler.err.class.method.or.field.expected=クラス、インタフェース、注釈型、列挙、レコード、メソッドまたはフィールドが必要です + ##### # Fatal Errors @@ -1589,6 +1590,7 @@ compiler.warn.proc.duplicate.option.name=重複するサポート対象オプシ # 0: string, 1: string compiler.warn.proc.duplicate.supported.annotation=重複するサポート対象注釈インタフェース''{0}''が注釈プロセッサ''{1}''によって返されました + # 0: string compiler.warn.proc.redundant.types.with.wildcard=注釈プロセッサ''{0}''は''*''と他の注釈インタフェースを重複してサポートします @@ -1671,6 +1673,9 @@ compiler.warn.annotation.method.not.found=タイプ''{0}''内に注釈メソッ # 0: type, 1: name, 2: message segment compiler.warn.annotation.method.not.found.reason=タイプ''{0}''内に注釈メソッド''{1}()''が見つかりません: {2} +# 0: list of annotation, 1: symbol, 2: name, 3: message segment +compiler.err.cant.attach.type.annotations=タイプ注釈{0}を{1}.{2}に添付できません:\n{3} + # 0: file object, 1: symbol, 2: name compiler.warn.unknown.enum.constant=不明な列挙型定数です{1}.{2} @@ -1806,7 +1811,11 @@ compiler.misc.bad.enclosing.class={0}の内部クラスが不正です: {1} # 0: symbol compiler.misc.bad.enclosing.method=クラス{0}の囲んでいるメソッド属性が不正です -compiler.misc.bad.runtime.invisible.param.annotations=RuntimeInvisibleParameterAnnotations属性が不正です: {0} +# 0: file name +compiler.warn.runtime.visible.invisible.param.annotations.mismatch={0}内のRuntimeVisibleParameterAnnotations属性およびRuntimeInvisibleParameterAnnotations属性内のパラメータの長さが一致しません。両方の属性を無視します + +# 0: file name +compiler.warn.runtime.invisible.parameter.annotations={0}内のRuntimeVisibleParameterAnnotationsおよびRuntimeInvisibleParameterAnnotations属性をメソッドのパラメータにマップできません compiler.misc.bad.const.pool.tag=定数プール・タグ{0}が不正です @@ -2038,6 +2047,10 @@ compiler.err.abstract.cant.be.accessed.directly=抽象{0}である{1}({2}内)に # 0: symbol kind, 1: symbol compiler.err.non-static.cant.be.ref=staticでない{0} {1}をstaticコンテキストから参照することはできません +## The first argument ({0}) is a "kindname". +# 0: symbol kind, 1: symbol +compiler.err.local.cant.be.inst.static=ローカル{0} {1}をstaticコンテキストからインスタンス化できません + # 0: symbol kind, 1: symbol compiler.misc.bad.static.method.in.unbound.lookup=非バインド検索で予期しない静的な{0} {1}が見つかりました @@ -2286,6 +2299,9 @@ compiler.misc.feature.flexible.constructors=柔軟なコンストラクタ compiler.misc.feature.module.imports=モジュール・インポート +# L10N: do not localize: transitive +compiler.misc.feature.java.base.transitive=java.baseの推移的修飾子 + compiler.warn.underscore.as.identifier=リリース9から''_''はキーワードなので識別子として使用することはできません compiler.err.underscore.as.identifier=リリース9から''_''はキーワードなので識別子として使用することはできません diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_zh_CN.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_zh_CN.properties index 54298cb23b9..c841c3715fc 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_zh_CN.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_zh_CN.properties @@ -635,6 +635,9 @@ compiler.err.limit.stack=代码需要过多堆栈 compiler.err.limit.string=常量字符串过长 +# 0: symbol +compiler.err.annotation.array.too.large="{0}" 中的批注数组元素太大 + # 0: string compiler.err.limit.string.overflow=对于常量池来说, 字符串 "{0}..." 的 UTF8 表示过长 @@ -656,9 +659,6 @@ compiler.misc.unexpected.ret.val=意外的返回值 # 0: set of flag compiler.err.mod.not.allowed.here=此处不允许使用修饰符{0} -# 0: name -compiler.err.modifier.not.allowed.here=此处不允许使用修饰符{0} - compiler.err.intf.not.allowed.here=此处不允许使用接口 # 0: symbol, 1: symbol @@ -781,9 +781,6 @@ compiler.err.not.def.access.class.intf.cant.access.reason=程序包 {2} 中的 { # 0: symbol, 1: symbol, 2: symbol, 3: message segment compiler.misc.not.def.access.class.intf.cant.access.reason=程序包 {2} 中的 {1}.{0} 不可访问\n({3}) -# 0: symbol, 1: list of type, 2: type -compiler.misc.cant.access.inner.cls.constr=无法访问构造器 {0}({1})\n作用域中没有类型为{2}的封闭实例 - # 0: symbol, 1: symbol compiler.err.not.def.public.cant.access={0}在{1}中不是公共的; 无法从外部程序包中对其进行访问 @@ -1148,6 +1145,10 @@ compiler.err.file.sb.on.source.or.patch.path.for.module=文件应在源路径或 compiler.err.no.java.lang=在平台类中找不到程序包 java.lang +compiler.err.statement.not.expected=语句不应在方法和初始化程序外部 + +compiler.err.class.method.or.field.expected=需要类、接口、批注类型、枚举、记录、方法或字段 + ##### # Fatal Errors @@ -1589,6 +1590,7 @@ compiler.warn.proc.duplicate.option.name=批注处理程序 ''{1}'' 返回重复 # 0: string, 1: string compiler.warn.proc.duplicate.supported.annotation=批注处理程序 ''{1}'' 返回重复的受支持批注接口 ''{0}'' + # 0: string compiler.warn.proc.redundant.types.with.wildcard=批注处理程序 ''{0}'' 重复支持 ''*'' 和其他批注接口 @@ -1671,6 +1673,9 @@ compiler.warn.annotation.method.not.found=无法找到类型 ''{0}'' 的批注 # 0: type, 1: name, 2: message segment compiler.warn.annotation.method.not.found.reason=无法找到类型 ''{0}'' 的批注方法 ''{1}()'': {2} +# 0: list of annotation, 1: symbol, 2: name, 3: message segment +compiler.err.cant.attach.type.annotations=无法将类型批注 {0} 附加到 {1}.{2}:\n{3} + # 0: file object, 1: symbol, 2: name compiler.warn.unknown.enum.constant=未知的枚举常量 {1}.{2} @@ -1806,7 +1811,11 @@ compiler.misc.bad.enclosing.class={0}的封闭类错误: {1} # 0: symbol compiler.misc.bad.enclosing.method=类 {0} 的封闭方法属性错误 -compiler.misc.bad.runtime.invisible.param.annotations=错误的 RuntimeInvisibleParameterAnnotations 属性: {0} +# 0: file name +compiler.warn.runtime.visible.invisible.param.annotations.mismatch={0} 中 RuntimeVisibleParameterAnnotations 属性和 RuntimeInvisibleParameterAnnotations 属性中的参数长度不匹配,将忽略这两个属性 + +# 0: file name +compiler.warn.runtime.invisible.parameter.annotations={0} 中的 RuntimeVisibleParameterAnnotations 属性和 RuntimeInvisibleParameterAnnotations 属性无法映射到方法的参数 compiler.misc.bad.const.pool.tag=错误的常量池标记: {0} @@ -2038,6 +2047,10 @@ compiler.err.abstract.cant.be.accessed.directly=无法直接访问{2}中的抽 # 0: symbol kind, 1: symbol compiler.err.non-static.cant.be.ref=无法从静态上下文中引用非静态 {0} {1} +## The first argument ({0}) is a "kindname". +# 0: symbol kind, 1: symbol +compiler.err.local.cant.be.inst.static=无法从静态上下文实例化本地 {0} {1} + # 0: symbol kind, 1: symbol compiler.misc.bad.static.method.in.unbound.lookup=在未绑定查找中找到意外的静态 {0} {1} @@ -2286,6 +2299,9 @@ compiler.misc.feature.flexible.constructors=灵活构造器 compiler.misc.feature.module.imports=模块导入 +# L10N: do not localize: transitive +compiler.misc.feature.java.base.transitive=java.base 的过渡修饰符 + compiler.warn.underscore.as.identifier=从发行版 9 开始, ''_'' 为关键字, 不能用作标识符 compiler.err.underscore.as.identifier=从发行版 9 开始, ''_'' 为关键字, 不能用作标识符 @@ -2738,7 +2754,7 @@ compiler.misc.local=本地 # errors related to records # record components -compiler.err.record.cant.declare.field.modifiers=记录组件不能具有限定符 +compiler.err.record.cant.declare.field.modifiers=记录组件不能具有修饰符 # 0: symbol compiler.err.illegal.record.component.name=记录组件名称 {0} 非法 diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_de.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_de.properties index 00b64b1f099..447695c9cf8 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_de.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_de.properties @@ -102,7 +102,7 @@ javac.opt.Xlint.all=Alle Warnungen aktivieren javac.opt.Xlint.none=Alle Warnungen deaktivieren #L10N: do not localize: -Xlint javac.opt.arg.Xlint=(,)* -javac.opt.Xlint.custom=Warnungen, die aktiviert oder deaktiviert werden sollen, durch Komma getrennt.\nStellen Sie einem Schlüssel "-" voran, um die angegebene Warnung zu deaktivieren.\nVerwenden Sie --help-lint, um die unterstützten Schlüssel zu sehen. +javac.opt.Xlint.custom=Warnungen, die aktiviert oder deaktiviert werden sollen, durch Komma getrennt.\nStellen Sie einem Schlüssel "-" voran, um die angegebene Warnung zu deaktivieren.\nVerwenden Sie "--help-lint", um die unterstützten Schlüssel anzuzeigen. javac.opt.Xlint.desc.auxiliaryclass=Warnt vor Auxiliary-Klassen, die in einer Quelldatei verborgen sind und aus anderen Dateien heraus verwendet werden. javac.opt.Xlint.desc.cast=Warnt vor unnötigen Umwandlungen mit Cast. @@ -187,7 +187,7 @@ javac.opt.Xdoclint.custom=Aktiviert oder deaktiviert bestimmte Prüfungen auf Pr javac.opt.Xdoclint.package.args = [-](,[-])* -javac.opt.Xdoclint.package.desc=Aktiviert oder deaktiviert Prüfungen in bestimmten Packages. Jedes ist entweder der\nqualifizierte Name eines Packages oder ein Packagenamenspräfix, gefolgt von ".*",\ndas sich auf alle Subpackages des angegebenen Packages bezieht. Jedem \nkann "-" vorangestellt werden, um Prüfungen für die angegebenen Packages zu deaktivieren. +javac.opt.Xdoclint.package.desc=Aktiviert oder deaktiviert Prüfungen in bestimmten Packages. Jedes ist entweder\nein qualifizierter Packagename oder ein Packagenamenspräfix, gefolgt von ".*",\ndas sich auf alle Subpackages des angegebenen Packages bezieht. Jedem \nkann "-" vorangestellt werden, um Prüfungen für die angegebenen Packages zu deaktivieren. javac.opt.Xstdout=Leitet die Standardausgabe um javac.opt.X=Gibt Hilfe zu zusätzlichen Optionen aus diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_ja.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_ja.properties index 4eb259b23cc..c215ad5eeba 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_ja.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_ja.properties @@ -102,7 +102,7 @@ javac.opt.Xlint.all=すべての警告を有効にします javac.opt.Xlint.none=すべての警告を無効にします #L10N: do not localize: -Xlint javac.opt.arg.Xlint=(,)* -javac.opt.Xlint.custom=有効または無効にする警告(カンマ区切り)。\n指定した警告を無効にするには、キーの前に'-'を指定します。\nサポートされているキーを表示するには--help-lintを使用します。 +javac.opt.Xlint.custom=有効または無効にする警告(カンマ区切り)。\n指定した警告を無効にするには、キーの前に''-''を指定します。\nサポートされているキーを表示するには--help-lintを使用します。 javac.opt.Xlint.desc.auxiliaryclass=ソース・ファイルで非表示になっているが他のファイルから使用されている補助クラスについて警告します。 javac.opt.Xlint.desc.cast=不要なキャストの使用について警告します。 @@ -187,7 +187,7 @@ javac.opt.Xdoclint.custom=javadocコメントの問題に関する特定のチ javac.opt.Xdoclint.package.args = [-](,[-])* -javac.opt.Xdoclint.package.desc=特定のパッケージのチェックを有効または無効にします。各は、\nパッケージの修飾された名前、またはパッケージ名の接頭辞の後に'.*'を\n指定(指定したパッケージのすべてのサブパッケージに拡張)したものです。各\nの前に'-'を指定すると、指定した1つ以上のパッケージに関するチェックを無効にできます。 +javac.opt.Xdoclint.package.desc=特定のパッケージのチェックを有効または無効にします。各は、\n修飾されたパッケージ名、またはパッケージ名の接頭辞の後に''.*''を\n指定(指定したパッケージのすべてのサブパッケージに拡張)したものです。各\nの前に''-''を指定すると、指定した1つ以上のパッケージに関するチェックを無効にできます。 javac.opt.Xstdout=標準出力をリダイレクトする javac.opt.X=追加オプションのヘルプを出力します @@ -216,7 +216,7 @@ javac.opt.module.version=コンパイルするモジュールのバージョン javac.opt.arg.module.version=<バージョン> javac.opt.inherit_runtime_environment=実行時環境からモジュール・システム構成オプションを継承します。 javac.opt.default.module.for.created.files=何も指定されていないか、推定型の場合、注釈プロセッサによって作成されるファイルのターゲット・モジュールをフォールバックします。 -javac.opt.lineDocComments='///'で行を開始すると、ドキュメンテーション・コメントのサポートが無効化されます +javac.opt.lineDocComments=''///''で行を開始すると、ドキュメンテーション・コメントのサポートが無効化されます ## messages diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_zh_CN.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_zh_CN.properties index 8cbddae86f6..1593280fd4d 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_zh_CN.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_zh_CN.properties @@ -87,7 +87,7 @@ javac.opt.arg.default.module.for.created.files= javac.opt.maxerrs=设置要输出的错误的最大数目 javac.opt.maxwarns=设置要输出的警告的最大数目 -javac.opt.nogj=语言中不接受泛型 +javac.opt.nogj=该语言不接受泛型 javac.opt.moreinfo=输出类型变量的扩展信息 javac.opt.printsearch=输出有关搜索类文件的位置的信息 javac.opt.prompt=在每次出错后停止 @@ -101,8 +101,8 @@ javac.opt.Xlint=启用建议的警告 javac.opt.Xlint.all=启用所有警告 javac.opt.Xlint.none=禁用所有警告 #L10N: do not localize: -Xlint -javac.opt.arg.Xlint=<密钥>(,<密钥>)* -javac.opt.Xlint.custom=要启用或禁用的警告,使用逗号分隔。\n在关键字前面加上 '-' 可禁用指定的警告。\n使用 --help-lint 可查看受支持的关键字。 +javac.opt.arg.Xlint=(,)* +javac.opt.Xlint.custom=要启用或禁用的警告(以逗号分隔)。\n在关键字前面加上 ''-'' 可禁用指定的警告。\n使用 --help-lint 可查看受支持的关键字。 javac.opt.Xlint.desc.auxiliaryclass=有关辅助类在源文件中隐藏, 但在其他文件中使用的警告。 javac.opt.Xlint.desc.cast=有关使用了不必要转换的警告。 @@ -187,7 +187,7 @@ javac.opt.Xdoclint.custom=为 javadoc 注释中的问题启用或禁用特定检 javac.opt.Xdoclint.package.args = [-]<程序包>(,[-]<程序包>)* -javac.opt.Xdoclint.package.desc=在特定的程序包中启用或禁用检查。每个 <程序包> 是\n程序包的限定名称,或程序包名称前缀后跟 '.*'\n(这将扩展到给定程序包的所有子程序包)。在每个 <程序包>\n前面加上 '-' 可以为指定程序包禁用检查。 +javac.opt.Xdoclint.package.desc=在特定的程序包中启用或禁用检查。每个 <程序包> 是\n限定的程序包名称,或程序包名称前缀后跟 ''.*''\n(这将扩展到给定程序包的所有子程序包)。在每个 <程序包>\n前面加上 ''-'' 可对指定程序包禁用检查。 javac.opt.Xstdout=重定向标准输出 javac.opt.X=输出额外选项的帮助 @@ -216,7 +216,7 @@ javac.opt.module.version=指定正在编译的模块版本 javac.opt.arg.module.version=<版本> javac.opt.inherit_runtime_environment=从运行时环境继承模块系统配置选项。 javac.opt.default.module.for.created.files=由批注处理程序创建的文件的备用目标模块 (如果未指定或推断任何模块)。 -javac.opt.lineDocComments=禁用对带有以 '///' 开头的行的文档注释的支持 +javac.opt.lineDocComments=禁用对带有以 ''///'' 开头的行的文档注释的支持 ## messages diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Names.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Names.java index 6c48490cf16..d9aec7c4592 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Names.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Names.java @@ -127,6 +127,7 @@ public static Names instance(Context context) { // module names public final Name java_base; + public final Name java_se; public final Name jdk_unsupported; // attribute names @@ -315,6 +316,7 @@ public Names(Context context) { // module names java_base = fromString("java.base"); + java_se = fromString("java.se"); jdk_unsupported = fromString("jdk.unsupported"); // attribute names diff --git a/src/jdk.incubator.vector/linux/native/libsleef/lib/vector_math_neon.c b/src/jdk.incubator.vector/linux/native/libsleef/lib/vector_math_neon.c index de289d4ffc5..efd5443607b 100644 --- a/src/jdk.incubator.vector/linux/native/libsleef/lib/vector_math_neon.c +++ b/src/jdk.incubator.vector/linux/native/libsleef/lib/vector_math_neon.c @@ -4,7 +4,9 @@ * * 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. + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or diff --git a/src/jdk.incubator.vector/linux/native/libsleef/lib/vector_math_rvv.c b/src/jdk.incubator.vector/linux/native/libsleef/lib/vector_math_rvv.c index 438ca0c92ba..c0972ee6db1 100644 --- a/src/jdk.incubator.vector/linux/native/libsleef/lib/vector_math_rvv.c +++ b/src/jdk.incubator.vector/linux/native/libsleef/lib/vector_math_rvv.c @@ -4,7 +4,9 @@ * * 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. + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or diff --git a/src/jdk.incubator.vector/linux/native/libsleef/lib/vector_math_sve.c b/src/jdk.incubator.vector/linux/native/libsleef/lib/vector_math_sve.c index 1a442761d51..4c80f9f7d37 100644 --- a/src/jdk.incubator.vector/linux/native/libsleef/lib/vector_math_sve.c +++ b/src/jdk.incubator.vector/linux/native/libsleef/lib/vector_math_sve.c @@ -4,7 +4,9 @@ * * 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. + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector.java index 346b00eda5e..b578390e50f 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector.java @@ -2869,6 +2869,10 @@ private static ReductionOperation> reductionOperati toBits(v.rOp(MAX_OR_INF, m, (i, a, b) -> (byte) Math.min(a, b))); case VECTOR_OP_MAX: return (v, m) -> toBits(v.rOp(MIN_OR_INF, m, (i, a, b) -> (byte) Math.max(a, b))); + case VECTOR_OP_UMIN: return (v, m) -> + toBits(v.rOp(MAX_OR_INF, m, (i, a, b) -> (byte) VectorMath.minUnsigned(a, b))); + case VECTOR_OP_UMAX: return (v, m) -> + toBits(v.rOp(MIN_OR_INF, m, (i, a, b) -> (byte) VectorMath.maxUnsigned(a, b))); case VECTOR_OP_AND: return (v, m) -> toBits(v.rOp((byte)-1, m, (i, a, b) -> (byte)(a & b))); case VECTOR_OP_OR: return (v, m) -> diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector.java index 390c8026083..9a46db33de8 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector.java @@ -2854,6 +2854,10 @@ private static ReductionOperation> reductionOpera toBits(v.rOp(MAX_OR_INF, m, (i, a, b) -> (int) Math.min(a, b))); case VECTOR_OP_MAX: return (v, m) -> toBits(v.rOp(MIN_OR_INF, m, (i, a, b) -> (int) Math.max(a, b))); + case VECTOR_OP_UMIN: return (v, m) -> + toBits(v.rOp(MAX_OR_INF, m, (i, a, b) -> (int) VectorMath.minUnsigned(a, b))); + case VECTOR_OP_UMAX: return (v, m) -> + toBits(v.rOp(MIN_OR_INF, m, (i, a, b) -> (int) VectorMath.maxUnsigned(a, b))); case VECTOR_OP_AND: return (v, m) -> toBits(v.rOp((int)-1, m, (i, a, b) -> (int)(a & b))); case VECTOR_OP_OR: return (v, m) -> diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector.java index 43fedc2693b..8963e52cab1 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector.java @@ -2720,6 +2720,10 @@ private static ReductionOperation> reductionOperati toBits(v.rOp(MAX_OR_INF, m, (i, a, b) -> (long) Math.min(a, b))); case VECTOR_OP_MAX: return (v, m) -> toBits(v.rOp(MIN_OR_INF, m, (i, a, b) -> (long) Math.max(a, b))); + case VECTOR_OP_UMIN: return (v, m) -> + toBits(v.rOp(MAX_OR_INF, m, (i, a, b) -> (long) VectorMath.minUnsigned(a, b))); + case VECTOR_OP_UMAX: return (v, m) -> + toBits(v.rOp(MIN_OR_INF, m, (i, a, b) -> (long) VectorMath.maxUnsigned(a, b))); case VECTOR_OP_AND: return (v, m) -> toBits(v.rOp((long)-1, m, (i, a, b) -> (long)(a & b))); case VECTOR_OP_OR: return (v, m) -> diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector.java index 552967d82e7..88965835e9b 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector.java @@ -2870,6 +2870,10 @@ private static ReductionOperation> reductionOpera toBits(v.rOp(MAX_OR_INF, m, (i, a, b) -> (short) Math.min(a, b))); case VECTOR_OP_MAX: return (v, m) -> toBits(v.rOp(MIN_OR_INF, m, (i, a, b) -> (short) Math.max(a, b))); + case VECTOR_OP_UMIN: return (v, m) -> + toBits(v.rOp(MAX_OR_INF, m, (i, a, b) -> (short) VectorMath.minUnsigned(a, b))); + case VECTOR_OP_UMAX: return (v, m) -> + toBits(v.rOp(MIN_OR_INF, m, (i, a, b) -> (short) VectorMath.maxUnsigned(a, b))); case VECTOR_OP_AND: return (v, m) -> toBits(v.rOp((short)-1, m, (i, a, b) -> (short)(a & b))); case VECTOR_OP_OR: return (v, m) -> diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/VectorMask.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/VectorMask.java index f5ce894b13f..cdf5b589be7 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/VectorMask.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/VectorMask.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -108,8 +108,6 @@ * } * * - * @param the boxed version of {@code ETYPE}, - * the element type of a vector * *

Value-based classes and identity operations

* @@ -128,6 +126,9 @@ * {@code static final} constants, but storing them in other Java * fields or in array elements, while semantically valid, may incur * performance penalties. + * + * @param the boxed version of {@code ETYPE}, + * the element type of a vector */ @SuppressWarnings("exports") public abstract class VectorMask extends jdk.internal.vm.vector.VectorSupport.VectorMask { diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-Vector.java.template b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-Vector.java.template index 7eb1d9810b1..de9c74130cb 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-Vector.java.template +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-Vector.java.template @@ -3375,6 +3375,12 @@ public abstract class $abstractvectortype$ extends AbstractVector<$Boxtype$> { toBits(v.rOp(MAX_OR_INF, m, (i, a, b) -> ($type$) Math.min(a, b))); case VECTOR_OP_MAX: return (v, m) -> toBits(v.rOp(MIN_OR_INF, m, (i, a, b) -> ($type$) Math.max(a, b))); +#if[!FP] + case VECTOR_OP_UMIN: return (v, m) -> + toBits(v.rOp(MAX_OR_INF, m, (i, a, b) -> ($type$) VectorMath.minUnsigned(a, b))); + case VECTOR_OP_UMAX: return (v, m) -> + toBits(v.rOp(MIN_OR_INF, m, (i, a, b) -> ($type$) VectorMath.maxUnsigned(a, b))); +#end[!FP] #if[BITWISE] case VECTOR_OP_AND: return (v, m) -> toBits(v.rOp(($type$)-1, m, (i, a, b) -> ($type$)(a & b))); diff --git a/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Main.java b/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Main.java index 014b420e1a2..5931e943e30 100644 --- a/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Main.java +++ b/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Main.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,7 +30,8 @@ import java.net.URLClassLoader; import java.security.cert.CertPathValidatorException; import java.security.cert.PKIXBuilderParameters; -import java.security.interfaces.ECKey; +import java.security.spec.ECParameterSpec; +import java.security.spec.NamedParameterSpec; import java.util.*; import java.util.stream.Collectors; import java.util.zip.*; @@ -1242,14 +1243,14 @@ private void displayMessagesAndResult(boolean isSigning) { if ((legacyAlg & 8) == 8) { warnings.add(String.format( - rb.getString("The.1.signing.key.has.a.keysize.of.2.which.is.considered.a.security.risk..This.key.size.will.be.disabled.in.a.future.update."), - KeyUtil.fullDisplayAlgName(privateKey), KeyUtil.getKeySize(privateKey))); + rb.getString("The.full.keyAlgName.signing.key.is.considered.a.security.risk..It.will.be.disabled.in.a.future.update."), + fullDisplayKeyName(privateKey))); } if ((disabledAlg & 8) == 8) { errors.add(String.format( - rb.getString("The.1.signing.key.has.a.keysize.of.2.which.is.considered.a.security.risk.and.is.disabled."), - KeyUtil.fullDisplayAlgName(privateKey), KeyUtil.getKeySize(privateKey))); + rb.getString("The.full.keyAlgName.signing.key.is.considered.a.security.risk.and.is.disabled."), + fullDisplayKeyName(privateKey))); } } else { if ((legacyAlg & 1) != 0) { @@ -1272,8 +1273,8 @@ private void displayMessagesAndResult(boolean isSigning) { if ((legacyAlg & 8) == 8) { warnings.add(String.format( - rb.getString("The.1.signing.key.has.a.keysize.of.2.which.is.considered.a.security.risk..This.key.size.will.be.disabled.in.a.future.update."), - KeyUtil.fullDisplayAlgName(weakPublicKey), KeyUtil.getKeySize(weakPublicKey))); + rb.getString("The.full.keyAlgName.signing.key.is.considered.a.security.risk..It.will.be.disabled.in.a.future.update."), + fullDisplayKeyName(weakPublicKey))); } } @@ -1448,35 +1449,53 @@ private String verifyWithWeak(String alg, Set primitiveSet, } private String verifyWithWeak(PublicKey key, JarConstraintsParameters jcp) { - int kLen = KeyUtil.getKeySize(key); + String fullName = fullDisplayKeyName(key); try { JAR_DISABLED_CHECK.permits(key.getAlgorithm(), jcp, true); } catch (CertPathValidatorException e) { disabledAlgFound = true; - if (key instanceof ECKey) { - return String.format(rb.getString("key.bit.eccurve.disabled"), kLen, - KeyUtil.fullDisplayAlgName(key)); - } else { - return String.format(rb.getString("key.bit.disabled"), kLen); - } + return String.format(rb.getString("key.bit.disabled"), fullName); } try { LEGACY_CHECK.permits(key.getAlgorithm(), jcp, true); - if (kLen >= 0) { - return String.format(rb.getString("key.bit"), kLen); - } else { - return rb.getString("unknown.size"); - } + return String.format(rb.getString("key.bit"), fullName); } catch (CertPathValidatorException e) { weakPublicKey = key; legacyAlg |= 8; - if (key instanceof ECKey) { - return String.format(rb.getString("key.bit.eccurve.weak"), kLen, - KeyUtil.fullDisplayAlgName(key)); - } else { - return String.format(rb.getString("key.bit.weak"), kLen); + return String.format(rb.getString("key.bit.weak"), fullName); + } + } + + /** + * Returns the full display name of the given key object. Could be + * - "X25519", if its getParams() is NamedParameterSpec + * - "EC (secp256r1)", if it's an EC key + * - "1024-bit RSA", other known keys + * - plain algorithm name, otherwise + * + * Note: the same method appears in keytool and jarsigner which uses + * same resource string defined in their own Resources.java. + * + * @param key the key object, cannot be null + * @return the full name + */ + private static String fullDisplayKeyName(Key key) { + var alg = key.getAlgorithm(); + if (key instanceof AsymmetricKey ak) { + var params = ak.getParams(); + if (params instanceof NamedParameterSpec nps) { + return nps.getName(); // directly return + } else if (params instanceof ECParameterSpec eps) { + var nc = CurveDB.lookup(eps); + if (nc != null) { + alg += " (" + nc.getNameAndAliases()[0] + ")"; // append name + } } } + var size = KeyUtil.getKeySize(key); + return size >= 0 + ? String.format(rb.getString("size.bit.alg"), size, alg) + : alg; } private void checkWeakSign(String alg, Set primitiveSet, @@ -1524,31 +1543,17 @@ private void checkWeakSign(PrivateKey key, JarConstraintsParameters jcp) { } private static String checkWeakKey(PublicKey key, CertPathConstraintsParameters cpcp) { - int kLen = KeyUtil.getKeySize(key); + String fullName = fullDisplayKeyName(key); try { CERTPATH_DISABLED_CHECK.permits(key.getAlgorithm(), cpcp, true); } catch (CertPathValidatorException e) { - if (key instanceof ECKey) { - return String.format(rb.getString("key.bit.eccurve.disabled"), kLen, - KeyUtil.fullDisplayAlgName(key)); - } else { - return String.format(rb.getString("key.bit.disabled"), kLen); - } + return String.format(rb.getString("key.bit.disabled"), fullName); } try { LEGACY_CHECK.permits(key.getAlgorithm(), cpcp, true); - if (kLen >= 0) { - return String.format(rb.getString("key.bit"), kLen); - } else { - return rb.getString("unknown.size"); - } + return String.format(rb.getString("key.bit"), fullName); } catch (CertPathValidatorException e) { - if (key instanceof ECKey) { - return String.format(rb.getString("key.bit.eccurve.weak"), kLen, - KeyUtil.fullDisplayAlgName(key)); - } else { - return String.format(rb.getString("key.bit.weak"), kLen); - } + return String.format(rb.getString("key.bit.weak"), fullName); } } diff --git a/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources.java b/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources.java index 810bd107bde..82d3fb0a2ae 100644 --- a/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources.java +++ b/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -173,12 +173,9 @@ public class Resources extends java.util.ListResourceBundle { {"with.algparams.weak", "%1$s using %2$s (weak)"}, {"with.disabled", "%s (disabled)"}, {"with.algparams.disabled", "%1$s using %2$s (disabled)"}, - {"key.bit", "%d-bit key"}, - {"key.bit.weak", "%d-bit key (weak)"}, - {"key.bit.eccurve.weak", "%1$d-bit %2$s key (weak)"}, - {"key.bit.disabled", "%d-bit key (disabled)"}, - {"key.bit.eccurve.disabled", "%1$d-bit %2$s key (disabled)"}, - {"unknown.size", "unknown size"}, + {"key.bit", "%s key"}, + {"key.bit.weak", "%s key (weak)"}, + {"key.bit.disabled", "%s key (disabled)"}, {"nonexistent.entries.found", "This jar contains signed entries for files that do not exist. See the -verbose output for more details."}, {"external.file.attributes.detected", "POSIX file permission and/or symlink attributes detected. These attributes are ignored when signing and are not protected by the signature."}, @@ -297,10 +294,12 @@ public class Resources extends java.util.ListResourceBundle { "The %1$s digest algorithm is considered a security risk. This algorithm will be disabled in a future update."}, {"The.signature.algorithm.1.is.considered.a.security.risk..This.algorithm.will.be.disabled.in.a.future.update.", "The %1$s signature algorithm is considered a security risk. This algorithm will be disabled in a future update."}, - {"The.1.signing.key.has.a.keysize.of.2.which.is.considered.a.security.risk..This.key.size.will.be.disabled.in.a.future.update.", - "The %1$s signing key has a keysize of %2$d which is considered a security risk. This key size will be disabled in a future update."}, - {"The.1.signing.key.has.a.keysize.of.2.which.is.considered.a.security.risk.and.is.disabled.", - "The %1$s signing key has a keysize of %2$d which is considered a security risk and is disabled."}, + {"size.bit.alg", + "%1$d-bit %2$s"}, + {"The.full.keyAlgName.signing.key.is.considered.a.security.risk..It.will.be.disabled.in.a.future.update.", + "The %s signing key is considered a security risk. It will be disabled in a future update."}, + {"The.full.keyAlgName.signing.key.is.considered.a.security.risk.and.is.disabled.", + "The %s signing key is considered a security risk and is disabled."}, {"This.jar.contains.entries.whose.certificate.chain.is.invalid.reason.1", "This jar contains entries whose certificate chain is invalid. Reason: %s"}, {"This.jar.contains.entries.whose.tsa.certificate.chain.is.invalid.reason.1", diff --git a/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources_de.java b/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources_de.java index b11c491be14..9e7e0c81b21 100644 --- a/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources_de.java +++ b/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources_de.java @@ -164,6 +164,7 @@ public class Resources_de extends java.util.ListResourceBundle { {"history.with.ts", "- Von \"%1$s\" signiert\n Digestalgorithmus: %2$s\n Signaturalgorithmus: %3$s, %4$s\n Zeitstempel von \"%6$s\" am %5$tc\n Digestalgorithmus f\u00FCr Zeitstempel: %7$s\n Signaturalgorithmus f\u00FCr Zeitstempel: %8$s, %9$s"}, {"history.without.ts", "- Von \"%1$s\" signiert\n Digestalgorithmus: %2$s\n Signaturalgorithmus: %3$s, %4$s"}, + {"history.nonexistent.entries", " Warnung: Nicht vorhandene signierte Eintr\u00E4ge: "}, {"history.unparsable", "- Signaturbezogene Datei %s kann nicht geparst werden"}, {"history.nosf", "- Signaturbezogene Datei META-INF/%s.SF fehlt"}, {"history.nobk", "- Blockdatei f\u00FCr signaturbezogene Datei META-INF/%s.SF fehlt"}, @@ -178,6 +179,7 @@ public class Resources_de extends java.util.ListResourceBundle { {"key.bit.disabled", "%d-Bit-Schl\u00FCssel (deaktiviert)"}, {"key.bit.eccurve.disabled", "%1$d-Bit-%2$s-Schl\u00FCssel (deaktiviert)"}, {"unknown.size", "unbekannte Gr\u00F6\u00DFe"}, + {"nonexistent.entries.found", "Diese JAR-Datei enth\u00E4lt signierte Eintr\u00E4ge f\u00FCr Dateien, die nicht vorhanden sind. Weitere Details finden Sie in der Verbose-Ausgabe (-verbose)."}, {"external.file.attributes.detected", "POSIX-Dateiberechtigung und/oder Symlink-Attribute erkannt. Diese Attribute werden bei der Signatur ignoriert und sind nicht durch die Signatur gesch\u00FCtzt."}, {"jarsigner.", "jarsigner: "}, diff --git a/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources_ja.java b/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources_ja.java index 3754d864ce1..315180339b2 100644 --- a/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources_ja.java +++ b/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources_ja.java @@ -164,6 +164,7 @@ public class Resources_ja extends java.util.ListResourceBundle { {"history.with.ts", "- \u7F72\u540D\u8005: \"%1$s\"\n \u30C0\u30A4\u30B8\u30A7\u30B9\u30C8\u30FB\u30A2\u30EB\u30B4\u30EA\u30BA\u30E0: %2$s\n \u7F72\u540D\u30A2\u30EB\u30B4\u30EA\u30BA\u30E0: %3$s\u3001%4$s\n \u30BF\u30A4\u30E0\u30B9\u30BF\u30F3\u30D7\u4ED8\u52A0\u8005: \"%6$s\" \u65E5\u6642: %5$tc\n \u30BF\u30A4\u30E0\u30B9\u30BF\u30F3\u30D7\u306E\u30C0\u30A4\u30B8\u30A7\u30B9\u30C8\u30FB\u30A2\u30EB\u30B4\u30EA\u30BA\u30E0: %7$s\n \u30BF\u30A4\u30E0\u30B9\u30BF\u30F3\u30D7\u306E\u7F72\u540D\u30A2\u30EB\u30B4\u30EA\u30BA\u30E0: %8$s\u3001%9$s"}, {"history.without.ts", "- \u7F72\u540D\u8005: \"%1$s\"\n \u30C0\u30A4\u30B8\u30A7\u30B9\u30C8\u30FB\u30A2\u30EB\u30B4\u30EA\u30BA\u30E0: %2$s\n \u7F72\u540D\u30A2\u30EB\u30B4\u30EA\u30BA\u30E0: %3$s\u3001%4$s"}, + {"history.nonexistent.entries", " \u8B66\u544A: \u5B58\u5728\u3057\u306A\u3044\u7F72\u540D\u6E08\u30A8\u30F3\u30C8\u30EA: "}, {"history.unparsable", "- \u7F72\u540D\u95A2\u9023\u30D5\u30A1\u30A4\u30EB%s\u3092\u89E3\u6790\u3067\u304D\u307E\u305B\u3093"}, {"history.nosf", "- \u7F72\u540D\u95A2\u9023\u30D5\u30A1\u30A4\u30EBMETA-INF/%s.SF\u304C\u3042\u308A\u307E\u305B\u3093"}, {"history.nobk", "- \u7F72\u540D\u95A2\u9023\u30D5\u30A1\u30A4\u30EBMETA-INF/%s.SF\u306E\u30D6\u30ED\u30C3\u30AF\u30FB\u30D5\u30A1\u30A4\u30EB\u304C\u3042\u308A\u307E\u305B\u3093"}, @@ -178,6 +179,7 @@ public class Resources_ja extends java.util.ListResourceBundle { {"key.bit.disabled", "%d\u30D3\u30C3\u30C8\u30FB\u30AD\u30FC (\u7121\u52B9)"}, {"key.bit.eccurve.disabled", "%1$d\u30D3\u30C3\u30C8%2$s\u30AD\u30FC(\u7121\u52B9)"}, {"unknown.size", "\u4E0D\u660E\u30B5\u30A4\u30BA"}, + {"nonexistent.entries.found", "\u3053\u306Ejar\u306B\u306F\u3001\u5B58\u5728\u3057\u306A\u3044\u30D5\u30A1\u30A4\u30EB\u306E\u7F72\u540D\u6E08\u30A8\u30F3\u30C8\u30EA\u304C\u542B\u307E\u308C\u307E\u3059\u3002\u8A73\u7D30\u306F\u3001-verbose\u51FA\u529B\u3092\u53C2\u7167\u3057\u3066\u304F\u3060\u3055\u3044\u3002"}, {"external.file.attributes.detected", "POSIX\u30D5\u30A1\u30A4\u30EB\u6A29\u9650\u307E\u305F\u306Fsymlink(\u3042\u308B\u3044\u306F\u305D\u306E\u4E21\u65B9)\u306E\u5C5E\u6027\u304C\u691C\u51FA\u3055\u308C\u307E\u3057\u305F\u3002\u7F72\u540D\u4E2D\u306F\u3053\u308C\u3089\u306E\u5C5E\u6027\u306F\u7121\u8996\u3055\u308C\u3001\u7F72\u540D\u306B\u3088\u3063\u3066\u4FDD\u8B77\u3055\u308C\u307E\u305B\u3093\u3002"}, {"jarsigner.", "jarsigner: "}, diff --git a/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources_zh_CN.java b/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources_zh_CN.java index 9e76346fca2..843ac92f6a7 100644 --- a/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources_zh_CN.java +++ b/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources_zh_CN.java @@ -164,6 +164,7 @@ public class Resources_zh_CN extends java.util.ListResourceBundle { {"history.with.ts", "- \u7531 \"%1$s\" \u7B7E\u540D\n \u6458\u8981\u7B97\u6CD5: %2$s\n \u7B7E\u540D\u7B97\u6CD5: %3$s, %4$s\n \u7531 \"%6$s\" \u4E8E %5$tc \u52A0\u65F6\u95F4\u6233\n \u65F6\u95F4\u6233\u6458\u8981\u7B97\u6CD5: %7$s\n \u65F6\u95F4\u6233\u7B7E\u540D\u7B97\u6CD5: %8$s, %9$s"}, {"history.without.ts", "- \u7531 \"%1$s\" \u7B7E\u540D\n \u6458\u8981\u7B97\u6CD5: %2$s\n \u7B7E\u540D\u7B97\u6CD5: %3$s, %4$s"}, + {"history.nonexistent.entries", "\u8B66\u544A\uFF1A\u4E0D\u5B58\u5728\u7684\u7B7E\u540D\u6761\u76EE\uFF1A "}, {"history.unparsable", "- \u65E0\u6CD5\u89E3\u6790\u7684\u4E0E\u7B7E\u540D\u76F8\u5173\u7684\u6587\u4EF6 %s"}, {"history.nosf", "- \u7F3A\u5C11\u4E0E\u7B7E\u540D\u76F8\u5173\u7684\u6587\u4EF6 META-INF/%s.SF"}, {"history.nobk", "- \u4E0E\u7B7E\u540D\u76F8\u5173\u7684\u6587\u4EF6 META-INF/%s.SF \u7F3A\u5C11\u5757\u6587\u4EF6"}, @@ -178,6 +179,7 @@ public class Resources_zh_CN extends java.util.ListResourceBundle { {"key.bit.disabled", "%d \u4F4D\u5BC6\u94A5\uFF08\u7981\u7528\uFF09"}, {"key.bit.eccurve.disabled", "%1$d \u4F4D %2$s \u5BC6\u94A5\uFF08\u7981\u7528\uFF09"}, {"unknown.size", "\u672A\u77E5\u5927\u5C0F"}, + {"nonexistent.entries.found", "\u6B64 jar \u7684\u6587\u4EF6\u5305\u542B\u4E0D\u5B58\u5728\u7684\u7B7E\u540D\u6761\u76EE\u3002\u6709\u5173\u66F4\u591A\u8BE6\u7EC6\u4FE1\u606F\uFF0C\u8BF7\u53C2\u89C1 -verbose \u8F93\u51FA\u3002"}, {"external.file.attributes.detected", "\u68C0\u6D4B\u5230 POSIX \u6587\u4EF6\u6743\u9650\u548C/\u6216 symlink \u5C5E\u6027\u3002\u8FD9\u4E9B\u5C5E\u6027\u5728\u8FDB\u884C\u7B7E\u540D\u65F6\u4F1A\u88AB\u5FFD\u7565\uFF0C\u4E0D\u53D7\u8BE5\u7B7E\u540D\u7684\u4FDD\u62A4\u3002"}, {"jarsigner.", "jarsigner: "}, diff --git a/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_de.properties b/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_de.properties index 85f8bb9fe29..e53f907b50e 100644 --- a/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_de.properties +++ b/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_de.properties @@ -44,6 +44,8 @@ error.write.file=Fehler beim Schreiben in vorhandener JAR-Datei error.create.dir={0}: Verzeichnis konnte nicht erstellt werden error.incorrect.length=Falsche Länge bei der Verarbeitung: {0} error.create.tempfile=Es konnte keine temporäre Datei erstellt werden +error.extract.multiple.dest.dir=Sie können die Option "-C" oder "--dir" nicht mehrmals mit der Option "-x" angeben +error.extract.pflag.not.allowed=Sie können nicht "-Px" mit der Option "-C" oder "--dir" angeben error.hash.dep=Abhängigkeiten bei Hashing-Modul {0}. Modul {1} kann nicht im Modulpfad gefunden werden error.module.options.without.info=--module-version oder --hash-modules ohne module-info.class error.no.operative.descriptor=Kein operativer Deskriptor für Release: {0} @@ -83,6 +85,7 @@ warn.validator.concealed.public.class=Warnung: Eintrag {0} ist eine öffentliche warn.release.unexpected.versioned.entry=Unerwarteter versionierter Eintrag {0} warn.index.is.ignored=Der JAR-Index (META-INF/INDEX.LIST) wird seit JDK 18 zur Laufzeit ignoriert warn.flag.is.deprecated=Warnung: Die Option {0} ist veraltet und wird möglicherweise ignoriert oder in einem zukünftigen Release entfernt\n +warn.option.is.ignored=Warnung: Die Option "{0}" ist mit der aktuellen Verwendung nicht gültig und wird ignoriert. out.added.manifest=Manifest wurde hinzugefügt out.added.module-info=module-info hinzugefügt: {0} out.automodule=Kein Moduldeskriptor gefunden. Automatisches Modul wurde abgeleitet. @@ -94,10 +97,12 @@ out.deflated=({0} % verkleinert) out.stored=(0 % gespeichert) out.create=\ erstellt: {0} out.extracted=extrahiert: {0} +out.kept=\ übersprungen: {0} vorhanden out.inflated=\ vergrößert: {0} out.size=(ein = {0}) (aus = {1}) +out.extract.dir=Extrahieren in Verzeichnis: {0} -usage.compat=Kompatibilitätsschnittstelle\nVerwendung: jar {ctxui}[vfmn0PMe] [jar-file] [manifest-file] [entry-point] [-C dir] files] ...\nOptionen:\n -c erstellt ein neues Archiv (einschließlich fehlender übergeordneter Verzeichnisse)\n -t listet das Inhaltsverzeichnis für das Archiv auf\n -x extrahiert die benannten (oder alle) Dateien aus dem Archiv\n -u aktualisiert ein vorhandenes Archiv\n -v generiert Verbose-Ausgabe zur Standardausgabe\n -f gibt den Archivdateinamen an\n -m schließt Manifestinformationen aus der angegebenen Manifestdatei ein\n -e gibt den Anwendungseinstiegspunkt für Standalone-Anwendungen an,\n die in einer ausführbaren JAR-Datei gebündelt sind\n -0 speichert nur, keine ZIP-Komprimierung\n -P behält die vorangestellten Komponenten "/" (absoluter Pfad) und ".." (übergeordnetes Verzeichnis) aus Dateinamen bei\n -M generiert keine Manifestdatei für die Einträge\n -i generiert Indexinformationen für die angegebenen JAR-Dateien\n -C wechselt zum angegebenen Verzeichnis und schließt die folgende Datei ein\nDateien, die Verzeichnisse sind, werden rekursiv verarbeitet.\nDie Namen der Manifestdatei, der Archivdatei und des Einstiegspunkts werden\nin der gleichen Reihenfolge wie die Flags "m", "f" und "e" angegeben.\n\nBeispiel 1: Zwei Klassendateien in einem Archiv namens classes.jar archivieren: \n jar cvf classes.jar Foo.class Bar.class \nBeispiel 2: Die vorhandene Manifestdatei "mymanifest" verwenden und alle\n Dateien im Verzeichnis "foo/" in "classes.jar" archivieren: \n jar cvfm classes.jar mymanifest -C foo/ .\n +usage.compat=Kompatibilitätsschnittstelle\nVerwendung: jar {ctxui}[vfmn0PMe] [jar-file] [manifest-file] [entry-point] [-C dir] files] ...\nOptionen:\n -c erstellt ein neues Archiv (einschließlich fehlender übergeordneter Verzeichnisse)\n -t listet das Inhaltsverzeichnis für das Archiv auf\n -x extrahiert die benannten (oder alle) Dateien aus dem Archiv\n -u aktualisiert ein vorhandenes Archiv\n -v generiert Verbose-Ausgabe zur Standardausgabe\n -f gibt den Archivdateinamen an\n -m schließt Manifestinformationen aus der angegebenen Manifestdatei ein\n -e gibt den Anwendungseinstiegspunkt für Standalone-Anwendungen an,\n die in einer ausführbaren JAR-Datei gebündelt sind\n -0 speichert nur, ohne ZIP-Komprimierung\n -P behält die vorangestellten Komponenten "/" (absoluter Pfad) und ".." (übergeordnetes Verzeichnis) aus Dateinamen bei\n -M generiert keine Manifestdatei für die Einträge\n -i generiert Indexinformationen für die angegebenen JAR-Dateien\n -C wechselt zum angegebenen Verzeichnis und schließt die folgende Datei ein\nDateien, die Verzeichnisse sind, werden rekursiv verarbeitet.\nBei Verwendung im Extraktionsmodus wird die JAR-Datei in das angegebene Verzeichnis extrahiert\nDie Namen der Manifestdatei, der Archivdatei und des Einstiegspunkts werden\nin der gleichen Reihenfolge wie die Kennzeichen "m", "f" und "e" angegeben.\n\nBeispiel 1: Zwei Klassendateien in einem Archiv namens classes.jar archivieren: \n jar cvf classes.jar Foo.class Bar.class \nBeispiel 2: Die vorhandene Manifestdatei "mymanifest" verwenden und alle\n Dateien im Verzeichnis "foo/" in "classes.jar" archivieren: \n jar cvfm classes.jar mymanifest -C foo/ .\n main.usage.summary=Verwendung: jar [OPTION...] [ [--release VERSION] [-C dir] Dateien] ... main.usage.summary.try=Verwenden Sie "jar --help", um weitere Informationen anzuzeigen. @@ -108,10 +113,10 @@ main.help.opt.main.create=\ -c, --create Erstellt das Archiv. Wen main.help.opt.main.generate-index=\ -i, --generate-index=FILE Generiert Indexinformationen für die angegebenen\n JAR-Archive. Diese Option ist veraltet und wird möglicherweise in \n einem zukünftigen Release entfernt. main.help.opt.main.list=\ -t, --list Das Inhaltsverzeichnis für das Archiv auflisten main.help.opt.main.update=\ -u, --update Ein vorhandenes JAR-Archiv aktualisieren -main.help.opt.main.extract=\ -x, --extract Benannte (oder alle) Dateien aus dem Archiv extrahieren +main.help.opt.main.extract=\ -x, --extract Extrahiert benannte (oder alle) Dateien aus dem Archiv.\n Wenn eine Datei mit demselben Namen mehrmals im\n Archiv enthalten ist, wird jede Kopie extrahiert. Dabei überschreiben (ersetzen) neuere Kopien\n ältere Kopien, es sei denn, "-k" ist angegeben. main.help.opt.main.describe-module=\ -d, --describe-module Gibt den Moduldeskriptor oder automatischen Modulnamen aus main.help.opt.main.validate=\ --validate Validiert den Inhalt des JAR-Archivs. Diese Option\n validiert, dass die von einem Multi-Release-JAR-Archiv\n exportierte API über die verschiedenen Releaseversionen\n hinweg konsistent ist. -main.help.opt.any=\ In jedem Modus gültige Vorgangsmodifikatoren:\n\n -C DIR Zum angegebenen Verzeichnis wechseln und die folgende\n Datei aufnehmen +main.help.opt.any=\ In jedem Modus gültige Vorgangsmodifikatoren:\n\n -C DIR Zum angegebenen Verzeichnis wechseln und die folgende\n Datei aufnehmen. Bei Verwendung im Extraktionsmodus wird\n die JAR-Datei in das angegebene Verzeichnis extrahiert main.help.opt.any.file=\ -f, --file=FILE Der Name der Archivdatei. Wenn Sie dies auslassen, wird entweder stdin oder\n stdout verwendet, je nach Vorgang\n --release VERSION Speichert alle der folgenden Dateien in einem versionierten Verzeichnis\n der JAR-Datei (d.h. META-INF/versions/VERSION/) main.help.opt.any.verbose=\ -v, --verbose Verbose-Ausgabe bei Standardausgabe generieren main.help.opt.create=\ Vorgangsmodifikatoren, die nur im Erstellungsmodus gültig sind:\n @@ -128,8 +133,12 @@ main.help.opt.create.update.warn-if-resolved=\ --warn-if-resolved Hinwe main.help.opt.create.update.index=\ Vorgangsmodifikatoren, die nur im Erstellungs-, Aktualisierungs- und Indexgenerierungsmodus gültig sind:\n main.help.opt.create.update.index.no-compress=\ -0, --no-compress Nur speichern, keine ZIP-Komprimierung verwenden main.help.opt.create.update.index.date=\ --date=TIMESTAMP Zeitstempel im erweiterten Datums-/Uhrzeitformat mit Zeitunterschied\n und optionaler Zeitzone nach ISO-8601, zur Verwendung für die Zeitstempel von\n Einträgen, z.B. "2022-02-12T12:30:00-05:00" +main.help.opt.extract=\ Vorgangsmodifikatoren, die nur im Extraktionsmodus gültig sind:\n +main.help.opt.extract.keep-old-files=\ -k, --keep-old-files Vorhandene Dateien nicht überschreiben.\n Wenn bereits ein JAR-Dateieintrag mit demselben Namen im\n Zielverzeichnis vorhanden ist, wird die vorhandene Datei nicht überschrieben.\n Wenn eine Datei also mehrmals in einem\n Archiv enthalten ist, werden ältere Kopien nicht durch neuere Kopien überschrieben.\n Beachten Sie zudem, dass bei einigen Dateisystemen die Groß-/Kleinschreibung ignoriert wird. main.help.opt.other=\ Weitere Optionen:\n main.help.opt.other.help=\ -?, -h, --help[:compat] Gibt diese Meldung oder optional die Kompatibilität, Hilfe an main.help.opt.other.help-extra=\ --help-extra Hilfe zu zusätzlichen Optionen main.help.opt.other.version=\ --version Programmversion ausgeben main.help.postopt=\ Ein Archiv ist ein modulares JAR-Archiv, wenn der Moduldeskriptor "module-info.class"\n in der Root der angegebenen Verzeichnisse oder in der Root des JAR-Archivs selbst\n vorhanden ist. Die folgenden Vorgänge sind nur gültig, wenn Sie ein modulares JAR-Archiv\n erstellen oder ein vorhandenes nicht modulares JAR-Archiv aktualisieren: "--module-version",\n "--hash-modules" und "--modulepath".\n\n Obligatorische oder optionale Argumente zu langen Optionen sind auch für die jeweils\n zugehörigen kurzen Optionen obligatorisch oder optional. +main.help.opt.extract=\ Vorgangsmodifikatoren, die nur im Extraktionsmodus gültig sind:\n +main.help.opt.extract.dir=\ --dir Verzeichnis, in das die JAR-Datei extrahiert wird diff --git a/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_ja.properties b/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_ja.properties index 0444689acd3..69e31e40e79 100644 --- a/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_ja.properties +++ b/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_ja.properties @@ -44,6 +44,8 @@ error.write.file=既存jarファイルの書込み中にエラーが発生しま error.create.dir=ディレクトリ{0}を作成できませんでした error.incorrect.length={0}の処理中に不正な長さがありました error.create.tempfile=一時ファイルを作成できませんでした +error.extract.multiple.dest.dir='-x'オプションでは複数の'-C'または'--dir'を指定できません +error.extract.pflag.not.allowed='-C'または'--dir'オプションでは'-Px'を指定できません error.hash.dep=モジュール{0}依存性のハッシュでモジュール{1}がモジュール・パスに見つかりません error.module.options.without.info=--module-versionまたは--hash-modulesのいずれかでmodule-info.classがありません error.no.operative.descriptor=リリースの操作ディスクリプタはありません: {0} @@ -83,6 +85,7 @@ warn.validator.concealed.public.class=警告 : エントリ{0}は、隠しパッ warn.release.unexpected.versioned.entry=予期しないバージョニング済エントリ{0} warn.index.is.ignored=JDK 18以降、JAR索引(META-INF/INDEX.LIST)は実行時に無視されます warn.flag.is.deprecated=警告: {0}オプションは非推奨であり、今後のリリースで無視または削除される可能性があります\n +warn.option.is.ignored=警告: {0}オプションは、現在の使用状況では有効ではありません。無視されます。 out.added.manifest=マニフェストが追加されました out.added.module-info=module-infoが追加されました: {0} out.automodule=モジュール・ディスクリプタが見つかりません。自動モジュールが導出されました。 @@ -94,10 +97,12 @@ out.deflated=({0}%収縮されました) out.stored=(0%格納されました) out.create=\ {0}が作成されました out.extracted={0}が抽出されました +out.kept=\ スキップされました: {0}が存在します out.inflated=\ {0}が展開されました out.size=(入={0})(出={1}) +out.extract.dir=ディレクトリに抽出しています: {0} -usage.compat=互換性インタフェース:\n使用方法: jar {ctxui}[vfmn0PMe] [jar-file] [manifest-file] [entry-point] [-C dir] files] ...\nオプション:\n -c アーカイブを新規作成する(欠落している親ディレクトリを含む)\n -t アーカイブの内容を一覧表示する\n -x 指定の(またはすべての)ファイルをアーカイブから抽出する\n -u 既存アーカイブを更新する\n -v 標準出力に詳細な出力を生成する\n -f アーカイブ・ファイル名を指定する\n -m 指定のマニフェスト・ファイルからマニフェスト情報を取り込む\n -e 実行可能jarファイルにバンドルされたスタンドアロン・アプリケーションの \n エントリ・ポイントを指定する\n -0 格納のみ。ZIP圧縮を使用しない\n -P ファイル名の先頭の'/' (絶対パス)および".." (親ディレクトリ)コンポーネントを保持する\n -M エントリのマニフェスト・ファイルを作成しない\n -i 指定のjarファイルの索引情報を生成する\n -C 指定のディレクトリに変更し、次のファイルを取り込む\nファイルがディレクトリの場合は再帰的に処理されます。\nマニフェスト・ファイル名、アーカイブ・ファイル名およびエントリ・ポイント名は、\nフラグ'm'、'f'、'e'の指定と同じ順番で指定する必要があります。\n\n例1: 2つのクラス・ファイルをアーカイブclasses.jarに保存する: \n jar cvf classes.jar Foo.class Bar.class \n例2: 既存のマニフェスト・ファイル'mymanifest'を使用し、foo/ディレクトリの\n 全ファイルを'classes.jar'にアーカイブする: \n jar cvfm classes.jar mymanifest -C foo/ .\n +usage.compat=互換性インタフェース:\n使用方法: jar {ctxui}[vfmn0PMe] [jar-file] [manifest-file] [entry-point] [-C dir] files] ...\nオプション:\n -c アーカイブを新規作成する(欠落している親ディレクトリを含む)\n -t アーカイブの内容を一覧表示する\n -x 指定の(またはすべての)ファイルをアーカイブから抽出する\n -u 既存アーカイブを更新する\n -v 標準出力に詳細な出力を生成する\n -f アーカイブ・ファイル名を指定する\n -m 指定のマニフェスト・ファイルからマニフェスト情報を取り込む\n -e 実行可能jarファイルにバンドルされたスタンドアロン・アプリケーションの \n エントリ・ポイントを指定する\n -0 格納のみ。ZIP圧縮を使用しない\n -P ファイル名の先頭の'/' (絶対パス)および".." (親ディレクトリ)コンポーネントを保持する\n -M エントリのマニフェスト・ファイルを作成しない\n -i 指定のjarファイルの索引情報を生成する\n -C 指定のディレクトリに変更し、次のファイルを取り込む\nファイルがディレクトリの場合は再帰的に処理されます。\n抽出モードで使用される場合、jarを指定のディレクトリに抽出します\nマニフェスト・ファイル名、アーカイブ・ファイル名およびエントリ・ポイント名は、\nフラグ'm'、'f'、'e'の指定と同じ順番で指定する必要があります。\n\n例1: 2つのクラス・ファイルをアーカイブclasses.jarに保存する: \n jar cvf classes.jar Foo.class Bar.class \n例2: 既存のマニフェスト・ファイル'mymanifest'を使用し、foo/ディレクトリの\n 全ファイルを'classes.jar'にアーカイブする: \n jar cvfm classes.jar mymanifest -C foo/ .\n main.usage.summary=使用方法: jar [OPTION...] [ [--release VERSION] [-C dir] files] ... main.usage.summary.try=詳細は、`jar --help'を実行してください。 @@ -108,10 +113,10 @@ main.help.opt.main.create=\ -c、--create アーカイブを作 main.help.opt.main.generate-index=\ -i, --generate-index=FILE 指定したjarアーカイブの索引情報を生成します。\n このオプションは非推奨であり、今後のリリースで\n 削除される可能性があります。 main.help.opt.main.list=\ -t、--list アーカイブの内容を一覧表示します main.help.opt.main.update=\ -u、--update 既存のjarアーカイブを更新します -main.help.opt.main.extract=\ -x、--extract 指定の(またはすべての)ファイルをアーカイブから抽出します +main.help.opt.main.extract=\ -x、--extract 指定の(またはすべての)ファイルをアーカイブから抽出します。\n 同じ名前のファイルがアーカイブに複数回出現する場合、\n 各コピーが抽出され、後のコピーにより、前のコピーが\n 上書き(置換)されます(-kが指定されている場合以外)。 main.help.opt.main.describe-module=\ -d, --describe-module モジュール・ディスクリプタまたは自動モジュール名を出力します main.help.opt.main.validate=\ --validate jarアーカイブの内容を検証します。このオプションは\n 複数リリースのjarアーカイブでエクスポートされたAPIが\n すべての異なるリリース・バージョンで一貫していることを\n 検証します。 -main.help.opt.any=\ どのモードでも有効な操作修飾子:\n\n -C DIR 指定のディレクトリに変更し、次のファイルを\n 取り込みます +main.help.opt.any=\ どのモードでも有効な操作修飾子:\n\n -C DIR 指定のディレクトリに変更し、次のファイルを\n 取り込みます。抽出モードで使用されている場合、jarを\n 指定のディレクトリに抽出します main.help.opt.any.file=\ -f、--file=FILE アーカイブ・ファイル名。省略した場合、stdinまたは\n stdoutのいずれかが操作に基づいて使用されます\n --release VERSION 次のすべてのファイルをjarのバージョニングされたディレクトリ\n (つまり、META-INF/versions/VERSION/)に配置します main.help.opt.any.verbose=\ -v、--verbose 標準出力に詳細な出力を生成します main.help.opt.create=\ 作成モードでのみ有効な操作修飾子:\n @@ -128,8 +133,12 @@ main.help.opt.create.update.warn-if-resolved=\ --warn-if-resolved モ main.help.opt.create.update.index=\ 作成、更新および索引生成モードでのみ有効な操作修飾子:\n main.help.opt.create.update.index.no-compress=\ -0, --no-compress 格納のみ。ZIP圧縮を使用しません main.help.opt.create.update.index.date=\ --date=TIMESTAMP オプションのタイムゾーン形式を指定したISO-8601拡張オフセット\n の日時のタイムスタンプ。エントリのタイムスタンプの使用例は、\n "2022-02-12T12:30:00-05:00"です +main.help.opt.extract=\ 抽出モードでのみ有効な操作修飾子:\n +main.help.opt.extract.keep-old-files=\ -k、--keep-old-files 既存のファイルを上書きしません。\n 同じ名前のJarファイル・エントリがターゲット・ディレクトリに\n 存在する場合、既存のファイルは上書きされません。\n 結果として、ファイルがアーカイブ内に複数回出現する場合、\n 後のコピーによって前のコピーは上書きされません。\n また、一部のファイル・システムでは、大/小文字が区別される場合があることに注意してください。 main.help.opt.other=\ その他のオプション:\n main.help.opt.other.help=\ -?、-h、--help[:compat] これ(オプションで互換性)をhelpに指定します main.help.opt.other.help-extra=\ --help-extra 追加オプションのヘルプを提供します main.help.opt.other.version=\ --version プログラム・バージョンを出力します main.help.postopt=\ モジュール・ディスクリプタ'module-info.class'が指定のディレクトリのルートまたは\n jarアーカイブ自体のルートにある場合、アーカイブはモジュラjarです。\n 次の操作は、モジュラjarの作成時または既存の非モジュラjarの更新時に\n のみ有効です: '--module-version'、\n '--hash-modules'および'--module-path'。\n\n ロング・オプションへの必須またはオプションの引数は、対応するショート・オプション\n に対しても必須またはオプションになります。 +main.help.opt.extract=\ 抽出モードでのみ有効な操作修飾子:\n +main.help.opt.extract.dir=\ --dir jarが抽出されるディレクトリ diff --git a/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_zh_CN.properties b/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_zh_CN.properties index 06167a5b895..afe840435ac 100644 --- a/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_zh_CN.properties +++ b/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_zh_CN.properties @@ -44,6 +44,8 @@ error.write.file=写入现有的 jar 文件时出错 error.create.dir={0}: 无法创建目录 error.incorrect.length=处理时遇到不正确的长度: {0} error.create.tempfile=无法创建临时文件 +error.extract.multiple.dest.dir=不能与 '-x' 选项一起多次指定 '-C' 或 '--dir' 选项 +error.extract.pflag.not.allowed=不能与 '-C' 或 '--dir' 选项一起指定 '-Px' error.hash.dep=正在对模块 {0} 的被依赖对象执行散列处理, 在模块路径中找不到模块 {1} error.module.options.without.info=--module-version 或 --hash-modules 之一没有 module-info.class error.no.operative.descriptor=没有发行版的有效描述符: {0} @@ -83,6 +85,7 @@ warn.validator.concealed.public.class=警告: 条目 {0} 是已隐藏程序包 warn.release.unexpected.versioned.entry=意外的版本化条目 {0} warn.index.is.ignored=自 JDK 18 起,在运行时忽略 JAR 索引 (META-INF/INDEX.LIST) warn.flag.is.deprecated=警告:{0} 选项已过时,可能会在未来发行版中忽略或删除。\n +warn.option.is.ignored=警告:{0} 选项对于当前用法无效,将忽略它。 out.added.manifest=已添加清单 out.added.module-info=已添加 module-info: {0} out.automodule=找不到模块描述符。已派生自动模块。 @@ -94,10 +97,12 @@ out.deflated=(压缩了 {0}%) out.stored=(存储了 0%) out.create=\ 已创建: {0} out.extracted=已提取: {0} +out.kept=\ 已跳过:{0} 已存在 out.inflated=\ 已解压: {0} out.size=(输入 = {0}) (输出 = {1}) +out.extract.dir=提取到目录:{0} -usage.compat=兼容性接口:\n用法:jar {ctxui}[vfmn0PMe] [jar-file] [manifest-file] [entry-point] [-C dir] files] ...\n选项:\n -c 创建新档案(包括缺少的父目录)\n -t 列出档案目录\n -x 从档案中提取指定的(或所有)文件\n -u 更新现有档案\n -v 在标准输出中生成详细输出\n -f 指定档案文件名\n -m 包含指定清单文件中的清单信息\n -e 为捆绑到可执行 jar 文件的独立应用程序\n 指定应用程序入口点\n -0 仅存储;不使用任何 ZIP 压缩\n -P 保留文件名中的前导 '/'(绝对路径)和 ".."(父目录)组成部分\n -M 不创建条目的清单文件\n -i 为指定的 jar 文件生成索引信息\n -C 更改为指定的目录并包含以下文件\n如果任何文件为目录,则对其进行递归处理。\n清单文件名、档案文件名和入口点名称的指定顺序\n与 'm', 'f' 和 'e' 标记的指定顺序相同。\n\n示例 1:将两个类文件归档到一个名为 classes.jar 的档案中:\n jar cvf classes.jar Foo.class Bar.class \n示例 2:使用现有的清单文件 'mymanifest' 并\n 将 foo/ 目录中的所有文件归档到 'classes.jar' 中:\n jar cvfm classes.jar mymanifest -C foo/。\n +usage.compat=兼容性接口:\n用法:jar {ctxui}[vfmn0PMe] [jar-file] [manifest-file] [entry-point] [-C dir] files] ...\n选项:\n -c 创建新档案(包括缺少的父目录)\n -t 列出档案目录\n -x 从档案中提取指定的(或所有)文件\n -u 更新现有档案\n -v 在标准输出中生成详细输出\n -f 指定档案文件名\n -m 包含指定清单文件中的清单信息\n -e 为捆绑到可执行 jar 文件的独立应用程序\n 指定应用程序入口点\n -0 仅存储;不使用任何 ZIP 压缩\n -P 保留文件名中的前导 '/'(绝对路径)和 ".."(父目录)组成部分\n -M 不创建条目的清单文件\n -i 为指定的 jar 文件生成索引信息\n -C 更改为指定的目录并包含以下文件\n如果任何文件为目录,则对其进行递归处理。\n在提取模式下使用时,将 jar 提取到指定目录\n清单文件名、档案文件名和入口点名称的指定顺序\n与 'm'、'f' 和 'e' 标记的指定顺序相同。\n\n示例 1:将两个类文件归档到一个名为 classes.jar 的档案中:\n jar cvf classes.jar Foo.class Bar.class \n示例 2:使用现有的清单文件 'mymanifest' 并\n 将 foo/ 目录中的所有文件归档到 'classes.jar' 中:\n jar cvfm classes.jar mymanifest -C foo/。\n main.usage.summary=用法: jar [OPTION...] [ [--release VERSION] [-C dir] files] ... main.usage.summary.try=尝试使用 `jar --help' 获取详细信息。 @@ -108,10 +113,10 @@ main.help.opt.main.create=\ -c, --create 创建档案。通过 -f main.help.opt.main.generate-index=\ -i, --generate-index=FILE 生成指定 jar 档案的索引信息。\n 此选项已过时,\n 可能会在未来发行版中删除。 main.help.opt.main.list=\ -t, --list 列出档案的目录 main.help.opt.main.update=\ -u, --update 更新现有 jar 档案 -main.help.opt.main.extract=\ -x, --extract 从档案中提取指定的 (或全部) 文件 +main.help.opt.main.extract=\ -x, --extract 从档案中提取指定的(或所有)文件。\n 如果某个同名的文件在档案中出现多次,\n 则将提取每个副本,除非指定 -k,否则\n 后面的副本将覆盖(替换)前面的副本。 main.help.opt.main.describe-module=\ -d, --describe-module 输出模块描述符或自动模块名称 main.help.opt.main.validate=\ --validate 验证 jar 档案的内容。此选项\n 将验证由多发行版 jar 档案导出\n 的 API 在所有不同的发行版本中\n 是否一致。 -main.help.opt.any=\ 在任意模式下有效的操作修饰符:\n\n -C DIR 更改为指定的目录并包含\n 以下文件 +main.help.opt.any=\ 在任意模式下有效的操作修饰符:\n\n -C DIR 更改为指定目录并包含\n 以下文件。在提取模式下使用时,\n 将 jar 提取到指定目录 main.help.opt.any.file=\ -f, --file=FILE 档案文件名。省略时, 基于操作\n 使用 stdin 或 stdout\n --release VERSION 将下面的所有文件都放在\n jar 的版本化目录中 (即 META-INF/versions/VERSION/) main.help.opt.any.verbose=\ -v, --verbose 在标准输出中生成详细输出 main.help.opt.create=\ 仅在创建模式下有效的操作修饰符:\n @@ -128,8 +133,12 @@ main.help.opt.create.update.warn-if-resolved=\ --warn-if-resolved 提 main.help.opt.create.update.index=\ 只在创建, 更新和生成索引模式下有效的操作修饰符:\n main.help.opt.create.update.index.no-compress=\ -0, --no-compress 仅存储; 不使用 ZIP 压缩 main.help.opt.create.update.index.date=\ --date=TIMESTAMP 具有可选时区的 ISO-8601 扩展偏移\n 日期时间格式的时间戳(用于条目的时间戳),\n 例如,"2022-02-12T12:30:00-05:00" +main.help.opt.extract=\ 仅在提取模式下有效的操作修饰符:\n +main.help.opt.extract.keep-old-files=\ -k, --keep-old-files 不覆盖现有文件。\n 如果目标目录中存在同名的 Jar 文件\n 条目,将不覆盖现有文件。\n 因此,如果某个文件在档案中出现多次,\n 后面的副本不会覆盖前面的副本。\n 另请注意,一些文件系统可能不区分大小写。 main.help.opt.other=\ 其他选项:\n main.help.opt.other.help=\ -?, -h, --help[:compat] 提供此帮助,也可以选择性地提供兼容性帮助 main.help.opt.other.help-extra=\ --help-extra 提供额外选项的帮助 main.help.opt.other.version=\ --version 输出程序版本 main.help.postopt=\ 如果模块描述符 'module-info.class' 位于指定目录的\n 根目录中, 或者位于 jar 档案本身的根目录中, 则\n 该档案是一个模块化 jar。以下操作只在创建模块化 jar,\n 或更新现有的非模块化 jar 时有效: '--module-version',\n '--hash-modules' 和 '--module-path'。\n\n 如果为长选项提供了必需参数或可选参数, 则它们对于\n 任何对应的短选项也是必需或可选的。 +main.help.opt.extract=\ 仅在提取模式下有效的操作修饰符:\n +main.help.opt.extract.dir=\ --dir jar 将提取到其中的目录 diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard_de.properties b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard_de.properties index c444f387a65..b4d3f94bad5 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard_de.properties +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard_de.properties @@ -135,6 +135,9 @@ doclet.Preview_Label=Vorschau doclet.Preview_Mark=PREVIEW doclet.Restricted_Methods=Eingeschränkte Methoden doclet.Restricted_Mark=RESTRICTED +doclet.searchTag=Suchtag +doclet.searchTags=Tags suchen +doclet.searchTagsSummary=Übersicht über Suchtags doclet.Terminally_Deprecated=Endgültig veraltet doclet.Terminally_Deprecated_Elements=Endgültig veraltete Elemente doclet.Terminally_Deprecated_In_Release=Endgültig veraltet in {0} @@ -169,6 +172,7 @@ doclet.Interfaces=Schnittstellen doclet.Enclosing_Class=Umschließende Klasse: doclet.Enclosing_Interface=Umschließende Schnittstelle: doclet.Inheritance_Tree=Vererbungsbaum +doclet.DefinedIn=Definiert in doclet.ReferencedIn=Referenziert in doclet.Section=Abschnitt doclet.External_Specification=Externe Spezifikation @@ -256,6 +260,8 @@ doclet.help.all_packages.body=Die Seite {0} enthält einen alphabetischen Index doclet.help.serial_form.body=Jede serialisierbare oder externalisierbare Klasse verfügt über eine Beschreibung der zugehörigen Serialisierungsfelder und -methoden. Diese Informationen sind eher für Implementierer als für Benutzer der API von Interesse. Die Navigationsleiste enthält zwar keinen Link, Sie können diese Informationen jedoch abrufen, indem Sie zu einer beliebigen serialisierten Klasse navigieren und im Abschnitt "Siehe auch" der Klassenbeschreibung auf "Serialisierte Form" klicken. # 0: link to Constant Values page doclet.help.constants.body=Auf der Seite {0} sind die statischen endgültigen Felder und deren Werte aufgeführt. +# 0: link to Search Tags page +doclet.help.searchTags.body=Auf der Seite "{0}" werden die in der Dokumentation definierten Suchtags aufgelistet. # 0: link to System Properties page doclet.help.systemProperties.body=Die Seite {0} listet Referenzen auf Systemeigenschaften auf. # 0: link to External Specifications page @@ -323,7 +329,9 @@ doclet.ReflectivePreviewAPI={0} bezieht sich auf mindestens eine reflektive Vors doclet.UsesDeclaredUsingPreview={0} bezieht sich auf mindestens einen Typ, der mit einem Vorschaufeature der Programmiersprache Java deklariert wird: {1}. doclet.PreviewTrailingNote1=Programme können {0} nur verwenden, wenn Vorschaufeatures aktiviert sind. doclet.PreviewTrailingNote2=Vorschaufeatures können in künftigen Releases entfernt oder zu permanenten Features der Java-Plattform hochgestuft werden. -doclet.RestrictedLeadingNote={0} ist eine eingeschränkte Methode der Java-Plattform. +doclet.PreviewJavaSERequiresTransitiveJavaBase=Indirekte Exporte aus dem Modul java.base sind mit der Direktive requires transitive java.base verknüpft. Das ist ein Vorschaufeature der Java-Sprache.
Programme können requires transitive java.base nur verwenden, wenn Vorschaufeatures aktiviert sind.
Vorschaufeatures können in einem zukünftigen Release entfernt oder zu permanenten Features der Java-Plattform hochgestuft werden.
+doclet.RestrictedMethod=eingeschränkte Methode +doclet.RestrictedLeadingNote={0} ist eine {1} der Java-Plattform. doclet.RestrictedTrailingNote1=Programme können {0} nur verwenden, wenn der Zugriff auf eingeschränkte Methoden aktiviert ist. doclet.RestrictedTrailingNote2=Eingeschränkte Methoden sind nicht sicher und können bei falscher Verwendung die JVM zum Absturz bringen oder zu einer Beschädigung des Arbeitsspeichers führen. doclet.Declared_Using_Preview.SEALED=Verschlüsselte Klassen @@ -362,7 +370,7 @@ doclet.usage.version.description=@version-Absätze aufnehmen doclet.usage.author.description=@author-Absätze aufnehmen -doclet.usage.docfilessubdirs.description=doc-file-Unterverzeichnisse rekursiv kopieren +doclet.usage.docfilessubdirs.description=Ermöglicht Deep Copying von "doc-files"-Verzeichnissen. Unterverzeichnisse und alle\nInhalte werden rekursiv in das Ziel kopiert doclet.usage.splitindex.description=Index in eine Datei pro Buchstabe aufteilen @@ -384,7 +392,7 @@ doclet.usage.header.description=Headertext für jede Seite aufnehmen doclet.usage.html5.description=Generiert eine HTML 5-Ausgabe. Diese Option wird nicht mehr benötigt. doclet.usage.footer.parameters= -doclet.usage.footer.description=Footertext für jede Seite aufnehmen +doclet.usage.footer.description=Diese Option wird nicht mehr unterstützt und gibt eine Warnung aus doclet.usage.top.parameters= doclet.usage.top.description=Oberen Text für jede Seite aufnehmen @@ -406,7 +414,7 @@ doclet.usage.link-platform-properties.parameters=< URL> doclet.usage.link-platform-properties.description=Link zu Plattformdokumentations-URLs, die in der Eigenschaftendatei auf deklariert sind doclet.usage.excludedocfilessubdir.parameters=,,... -doclet.usage.excludedocfilessubdir.description=doc-files-Unterverzeichnisse mit angegebenem Namen ausschließen.\n":" kann überall im Argument als Trennzeichen verwendet werden. +doclet.usage.excludedocfilessubdir.description=Schließen Sie alle "doc-files"-Unterverzeichnisse mit einem angegebenen Namen aus.\n":" kann überall im Argument als Trennzeichen verwendet werden. doclet.usage.group.parameters= ,... doclet.usage.group.description=Angegebene Elemente auf Überblickseite gruppieren.\n":" kann überall im Argument als Trennzeichen verwendet werden. @@ -443,7 +451,7 @@ doclet.usage.nonavbar.description=Navigationsleiste nicht generieren doclet.usage.nooverview.description=Überblickseiten nicht generieren -doclet.usage.serialwarn.description=Warnung wegen @serial-Tag generieren +doclet.usage.serialwarn.description=Gibt Warnungen zur Kompilierzeit für fehlende "@serial"-Tags aus doclet.usage.since.parameters=(,)* doclet.usage.since.description=Dokumentiert die neue und die veraltete API in den angegebenen Releases @@ -452,7 +460,7 @@ doclet.usage.since-label.parameters= doclet.usage.since-label.description=Liefert Text für die Überschrift der Seite "Neue API" doclet.usage.tag.parameters=::
-doclet.usage.tag.description=Benutzerdefinierte Tags mit einem Argument angeben +doclet.usage.tag.description=Gibt ein benutzerdefiniertes Tag mit einem einzelnen Argument an doclet.usage.taglet.description=Vollqualifizierter Name des zu registrierenden Taglets @@ -468,7 +476,7 @@ doclet.usage.charset.description=Zeichensatz für plattformübergreifende Anzeig doclet.usage.javafx.description=Aktiviert die JavaFX-Funktionalität doclet.usage.helpfile.parameters= -doclet.usage.helpfile.description=Datei aufnehmen, zu der der Hilfelink verlinkt +doclet.usage.helpfile.description=Gibt eine Datei an, die den Text enthält, der beim Klicken auf den\nHilfelink in der Navigationsleiste angezeigt wird doclet.usage.linksource.description=Quelle in HTML generieren @@ -491,7 +499,7 @@ doclet.usage.override-methods.parameters=(detail|summary) doclet.usage.override-methods.description=Außer Kraft gesetzte Methoden im Abschnitt "detail" oder "summary" dokumentieren.\nDer Standardwert ist "detail". -doclet.usage.allow-script-in-comments.description=JavaScript in Optionen und Kommentaren zulassen +doclet.usage.allow-script-in-comments.description=JavaScript in Dokumentationskommentaren und Optionen\nzulassen, die HTML-Code enthalten doclet.usage.xdocrootparent.parameters=< URL> doclet.usage.xdocrootparent.description=Ersetzt alle Vorkommen von @docRoot gefolgt von /.. in doc-Kommentaren durch\n diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard_ja.properties b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard_ja.properties index ce56bc16325..31e745301b6 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard_ja.properties +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard_ja.properties @@ -135,6 +135,9 @@ doclet.Preview_Label=プレビュー doclet.Preview_Mark=PREVIEW doclet.Restricted_Methods=制限されたメソッド doclet.Restricted_Mark=RESTRICTED +doclet.searchTag=検索タグ +doclet.searchTags=タグの検索 +doclet.searchTagsSummary=検索タグ・サマリー doclet.Terminally_Deprecated=最終的に非推奨 doclet.Terminally_Deprecated_Elements=最終的に非推奨になった要素 doclet.Terminally_Deprecated_In_Release={0}で最終的に非推奨 @@ -169,6 +172,7 @@ doclet.Interfaces=インタフェース doclet.Enclosing_Class=含まれているクラス: doclet.Enclosing_Interface=含まれているインタフェース: doclet.Inheritance_Tree=継承ツリー +doclet.DefinedIn=定義先 doclet.ReferencedIn=参照 doclet.Section=セクション doclet.External_Specification=外部仕様 @@ -256,6 +260,8 @@ doclet.help.all_packages.body={0}ページには、ドキュメントに含ま doclet.help.serial_form.body=直列化可能または外部化可能な各クラスは、直列化フィールドとメソッドの説明を含みます。この情報は、APIを使用するのではなく、実装するユーザーに役立ちます。ナビゲーション・バーにリンクがない場合、直列化されたクラスに移動して、クラス記述の「関連項目」セクションにある「直列化された形式」をクリックすることにより、この情報を表示できます。 # 0: link to Constant Values page doclet.help.constants.body={0}ページには、static finalフィールドとその値のリストがあります。 +# 0: link to Search Tags page +doclet.help.searchTags.body={0}ページには、ドキュメントに定義されている検索タグがあります。 # 0: link to System Properties page doclet.help.systemProperties.body={0}ページには、システム・プロパティへの参照のリストがあります。 # 0: link to External Specifications page @@ -323,7 +329,9 @@ doclet.ReflectivePreviewAPI={0}は1つ以上のリフレクティブ・プレビ doclet.UsesDeclaredUsingPreview={0}は、Java言語のプレビュー機能を使用して宣言されている、1つ以上のタイプを参照しています: {1}。 doclet.PreviewTrailingNote1=プログラムは、プレビュー機能が有効になっている場合にのみ{0}を使用できます。 doclet.PreviewTrailingNote2=プレビュー機能は将来のリリースで削除されるか、Javaプラットフォームの永続的な機能にアップグレードされる可能性があります。 -doclet.RestrictedLeadingNote={0}はJavaプラットフォームの制限されたメソッドです。 +doclet.PreviewJavaSERequiresTransitiveJavaBase=java.baseモジュールからの間接的エクスポートは、Java言語のプレビュー機能であるrequires transitive java.baseディレクティブに関連付けられています。
プログラムは、プレビュー機能が有効になっている場合にのみrequires transitive java.baseを使用できます。
プレビュー機能は将来のリリースで削除されるか、Javaプラットフォームの永続的な機能にアップグレードされる可能性があります。
+doclet.RestrictedMethod=制限されたメソッド +doclet.RestrictedLeadingNote={0}は、Javaプラットフォームの{1}です。 doclet.RestrictedTrailingNote1=プログラムは、制限されたメソッドへのアクセスが有効になっている場合にのみ{0}を使用できます。 doclet.RestrictedTrailingNote2=制限されたメソッドは安全ではありません。不適切に使用した場合、JVMがクラッシュまたはメモリーが破損する場合があります。 doclet.Declared_Using_Preview.SEALED=シール・クラス @@ -362,7 +370,7 @@ doclet.usage.version.description=@versionパラグラフを含めます doclet.usage.author.description=@authorパラグラフを含めます -doclet.usage.docfilessubdirs.description=doc-fileサブディレクトリを再帰的にコピーします +doclet.usage.docfilessubdirs.description='doc-files'ディレクトリのディープ・コピーを有効にします。\n宛先には、サブディレクトリとそのすべて内容が再帰的にコピーされます doclet.usage.splitindex.description=1字ごとに1ファイルに索引を分割します @@ -384,7 +392,7 @@ doclet.usage.header.description=各ページにヘッダー・テキストを含 doclet.usage.html5.description=HTML 5出力を生成します。このオプションは必須ではなくなりました。 doclet.usage.footer.parameters= -doclet.usage.footer.description=各ページにフッター・テキストを含めます +doclet.usage.footer.description=このオプションはされなくなったため、警告が報告されます doclet.usage.top.parameters= doclet.usage.top.description=各ページに上部テキストを含めます @@ -406,7 +414,7 @@ doclet.usage.link-platform-properties.parameters= doclet.usage.link-platform-properties.description=にあるプロパティ・ファイルで宣言されているプラットフォーム・ドキュメントのURLにリンクします doclet.usage.excludedocfilessubdir.parameters=,,... -doclet.usage.excludedocfilessubdir.description=指定された名前のdoc-filesサブディレクトリをすべて除外します。\n':'も、セパレータとして引数の任意の場所に使用できます。 +doclet.usage.excludedocfilessubdir.description=指定された名前の'doc-files'サブディレクトリをすべて除外します。\n':'も、セパレータとして引数の任意の場所に使用できます。 doclet.usage.group.parameters= ,... doclet.usage.group.description=指定する要素を概要ページにおいてグループ化します。\n':'も、セパレータとして引数の任意の場所に使用できます。 @@ -443,7 +451,7 @@ doclet.usage.nonavbar.description=ナビゲーション・バーを生成しま doclet.usage.nooverview.description=概要ページを生成しません -doclet.usage.serialwarn.description=@serialタグに関する警告を生成しません +doclet.usage.serialwarn.description='@serial'タグがない場合は、コンパイル時に警告を報告します doclet.usage.since.parameters=(,)* doclet.usage.since.description=指定されたリリースの新規および非推奨のAPIをドキュメント化します @@ -468,7 +476,7 @@ doclet.usage.charset.description=生成されるドキュメントのクロス doclet.usage.javafx.description=JavaFX機能を有効にします doclet.usage.helpfile.parameters= -doclet.usage.helpfile.description=ヘルプ・リンクのリンク先ファイルを含めます +doclet.usage.helpfile.description=ナビゲーション・バー内のヘルプ・リンクがクリックされたときに表示される\nテキストを含むファイルを指定します doclet.usage.linksource.description=HTML形式でソースを生成します @@ -491,7 +499,7 @@ doclet.usage.override-methods.parameters=(詳細|要約) doclet.usage.override-methods.description=オーバーライドされたメソッドを詳細または要約セクションでドキュメント化します。\nデフォルトは詳細です。 -doclet.usage.allow-script-in-comments.description=オプションおよびコメントでJavaScriptを許可します +doclet.usage.allow-script-in-comments.description=ドキュメント・コメント、および値がhtml-codeであるオプションで\nJavaScriptを許可します doclet.usage.xdocrootparent.parameters= doclet.usage.xdocrootparent.description=docコメント内の/..が後に続く@docRootのすべてをで置換します diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard_zh_CN.properties b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard_zh_CN.properties index c109d4c4237..36e27355b63 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard_zh_CN.properties +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard_zh_CN.properties @@ -135,6 +135,9 @@ doclet.Preview_Label=预览 doclet.Preview_Mark=PREVIEW doclet.Restricted_Methods=受限制的方法 doclet.Restricted_Mark=RESTRICTED +doclet.searchTag=搜索标记 +doclet.searchTags=搜索标记 +doclet.searchTagsSummary=搜索标记概要 doclet.Terminally_Deprecated=最终已过时 doclet.Terminally_Deprecated_Elements=最终已过时的元素 doclet.Terminally_Deprecated_In_Release=最终在 {0} 中已过时 @@ -169,6 +172,7 @@ doclet.Interfaces=接口 doclet.Enclosing_Class=封闭类: doclet.Enclosing_Interface=封闭接口: doclet.Inheritance_Tree=继承树 +doclet.DefinedIn=定义位置 doclet.ReferencedIn=参考位置 doclet.Section=节 doclet.External_Specification=外部规范 @@ -256,6 +260,8 @@ doclet.help.all_packages.body={0} 包含文档中所有程序包的按字母顺 doclet.help.serial_form.body=每个可序列化或可外部化的类都有其序列化字段和方法的说明。此信息对实施(而非使用)API 的人员有用。尽管导航栏中没有链接,但您可以通过下列方式获取此信息:转至任何序列化类,然后单击类说明的“另请参阅”部分中的“序列化形式”。 # 0: link to Constant Values page doclet.help.constants.body={0}页面列出了静态最终字段及其值。 +# 0: link to Search Tags page +doclet.help.searchTags.body={0} 页面列出了文档中定义的搜索标记。 # 0: link to System Properties page doclet.help.systemProperties.body={0} 页面列出了对系统属性的引用。 # 0: link to External Specifications page @@ -323,7 +329,9 @@ doclet.ReflectivePreviewAPI={0} 引用一个或多个反射预览 API:{1}。 doclet.UsesDeclaredUsingPreview={0} 引用一个或多个类型,这些类型是使用 Java 语言 {1} 的预览功能声明的。 doclet.PreviewTrailingNote1=只有在启用了预览功能时,程序才能使用 {0}。 doclet.PreviewTrailingNote2=预览功能可能会在未来发行版中删除,也可能会升级为 Java 平台的永久功能。 -doclet.RestrictedLeadingNote={0} 是 Java 平台的受限制方法。 +doclet.PreviewJavaSERequiresTransitiveJavaBase=来自 java.base 模块的间接导出项与 requires transitive java.base 指令关联,这是 Java 语言的预览功能。
仅在启用了预览功能时,程序才能使用 requires transitive java.base
预览功能可能会在未来发行版中删除,也可能会升级为 Java 平台的永久功能。
+doclet.RestrictedMethod=受限制方法 +doclet.RestrictedLeadingNote={0} 是 Java 平台的 {1}。 doclet.RestrictedTrailingNote1=只有在启用了对受限制方法的访问时,程序才能使用 {0}。 doclet.RestrictedTrailingNote2=受限制的方法不安全,如果使用不当,可能会导致 JVM 崩溃或内存损坏。 doclet.Declared_Using_Preview.SEALED=密封类 @@ -362,7 +370,7 @@ doclet.usage.version.description=包含 @version 段 doclet.usage.author.description=包含 @author 段 -doclet.usage.docfilessubdirs.description=递归复制文档文件子目录 +doclet.usage.docfilessubdirs.description=启用对 'doc-files' 目录的深层复制。\n子目录和所有内容将递归复制到目标 doclet.usage.splitindex.description=将索引分为每个字母对应一个文件 @@ -384,7 +392,7 @@ doclet.usage.header.description=包含每个页面的页眉文本 doclet.usage.html5.description=生成 HTML 5 输出。此选项不再是必需的。 doclet.usage.footer.parameters= -doclet.usage.footer.description=包含每个页面的页脚文本 +doclet.usage.footer.description=此选项不再受支持,并会报告警告 doclet.usage.top.parameters= doclet.usage.top.description=包含每个页面的顶部文本 @@ -406,7 +414,7 @@ doclet.usage.link-platform-properties.parameters= doclet.usage.link-platform-properties.description=链接到位于 的属性文件中声明的平台文档 URL doclet.usage.excludedocfilessubdir.parameters=,,... -doclet.usage.excludedocfilessubdir.description=排除包含给定名称的所有 doc-files 子目录。\n还可以将 ':' 作为分隔符用于参数中的任何位置。 +doclet.usage.excludedocfilessubdir.description=排除包含给定名称的所有 'doc-files' 子目录。\n还可以将 ':' 作为分隔符用于参数中的任何位置。 doclet.usage.group.parameters= ,... doclet.usage.group.description=在概览页面上将指定元素归到一组。\n还可以将 ':' 作为分隔符用于参数中的任何位置。 @@ -443,7 +451,7 @@ doclet.usage.nonavbar.description=不生成导航栏 doclet.usage.nooverview.description=不生成概览页面 -doclet.usage.serialwarn.description=生成有关 @serial 标记的警告 +doclet.usage.serialwarn.description=针对缺少 '@serial' 标记,报告编译时警告 doclet.usage.since.parameters=(,)* doclet.usage.since.description=记录所指定发行版中新增和已过时的 API @@ -452,7 +460,7 @@ doclet.usage.since-label.parameters= doclet.usage.since-label.description=提供要在“新增 API”页的标题中使用的文本 doclet.usage.tag.parameters=::
-doclet.usage.tag.description=指定单个参数定制标记 +doclet.usage.tag.description=使用单个参数指定定制标记 doclet.usage.taglet.description=要注册的 Taglet 的全限定名称 @@ -468,7 +476,7 @@ doclet.usage.charset.description=用于跨平台查看生成的文档的字符 doclet.usage.javafx.description=启用 JavaFX 功能 doclet.usage.helpfile.parameters= -doclet.usage.helpfile.description=包含帮助链接所链接到的文件 +doclet.usage.helpfile.description=指定一个文件,其中包含在单击导航栏中的\n帮助链接时将显示的文本 doclet.usage.linksource.description=以 HTML 格式生成源文件 @@ -491,7 +499,7 @@ doclet.usage.override-methods.parameters=(detail|summary) doclet.usage.override-methods.description=在详细信息部分或概要部分中记录被覆盖的方法。\n默认值为 'detail'。 -doclet.usage.allow-script-in-comments.description=允许在选项和注释中使用 JavaScript +doclet.usage.allow-script-in-comments.description=允许在文档注释和选项中使用 JavaScript\n其值为 html-code doclet.usage.xdocrootparent.parameters= doclet.usage.xdocrootparent.description=将文档注释中出现的所有后跟 /.. 的 @docRoot 替换为\n diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_ja.properties b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_ja.properties index 1b00ea9fbc0..28126387ead 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_ja.properties +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_ja.properties @@ -282,7 +282,7 @@ doclet.record_equals_doc.fullbody.tail.both=参照コンポーネントは{@link doclet.record_equals_doc.fullbody.tail.primitive=このレコード・クラスのすべてのコンポーネントは対応するラッパー・クラスのcompareメソッドで比較されます。 -doclet.record_equals_doc.fullbody.tail.reference=このレコード・クラスのすべてのコンポーネントは{@link java.util.Objects#equals(Object,Object) Objects::equals(Object,Object)}と比較されます。 +doclet.record_equals_doc.fullbody.tail.reference=このレコード・クラスのすべてのコンポーネントは{@link java.util.Objects#equals(Object,Object) Objects::equals(Object,Object)}で比較されます。 doclet.record_equals_doc.param_name=比較するオブジェクト diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_zh_CN.properties b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_zh_CN.properties index e9786173c5f..e2722f1deab 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_zh_CN.properties +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_zh_CN.properties @@ -218,7 +218,7 @@ doclet.Annotation_Type_Optional_Members=可选元素 doclet.Annotation_Type_Required_Members=所需元素 doclet.Enum_Constants=枚举常量 doclet.Nested_Classes=嵌套类 -doclet.Modifier=限定符 +doclet.Modifier=修饰符 doclet.Type=类型 doclet.Modifier_and_Type=修饰符和类型 doclet.Implementation=实现: diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc_de.properties b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc_de.properties index 2192bfb3395..4d0e7bae176 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc_de.properties +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc_de.properties @@ -50,18 +50,18 @@ main.opt.package.desc=Zeigt Package-/geschützte/öffentliche Typen und Mitglied main.opt.private.desc=Zeigt alle Typen und Mitglieder. Zeigt bei benannten Modulen\nalle Packages und alle Moduldetails. main.opt.show.members.arg= -main.opt.show.members.desc=Gibt an, welche Mitglieder (Felder, Methoden usw.) dokumentiert\nwerden, wobei der Wert "public", "protected",\n"package" oder "private" lauten kann. Der Standardwert ist "protected"\nund zeigt öffentliche und geschützte Mitglieder, "public" zeigt nur\nöffentliche Mitglieder, "package" zeigt öffentliche, geschützte und\nPackagemitglieder, und "private" zeigt alle Mitglieder. +main.opt.show.members.desc=Gibt an, welche Member (Felder, Methoden oder Konstruktoren) dokumentiert\nwerden, wobei der Wert "public", "protected",\n"package" oder "private" lauten kann. Der Standardwert ist "protected"\nund zeigt öffentliche und geschützte Member an. "public" zeigt nur\nöffentliche Member, "package" zeigt öffentliche, geschützte und\nPackage-Member, und "private" zeigt alle Member an. main.opt.show.types.arg= main.opt.show.types.desc=Gibt an, welche Typen (Klassen, Schnittstellen usw.) dokumentiert\nwerden, wobei der Wert "public", "protected",\n"package" oder "private" lauten kann. Der Standardwert ist "protected"\nund zeigt öffentliche und geschützte Typen, "public" zeigt nur\nöffentliche Typen, "package" zeigt öffentliche, geschützte und\nPackagetypen, und "private" zeigt alle Typen. main.opt.show.packages.arg= -main.opt.show.packages.desc=Gibt das Modul an, dessen Packages dokumentiert werden. Mögliche\nWerte sind "exported" oder "all" (exportierte oder alle Packages). +main.opt.show.packages.desc=Gibt an, welche Modulpackages dokumentiert werden. Mögliche\nWerte sind "exported" oder "all" (exportierte oder alle Packages). main.opt.show.module.contents.arg= main.opt.show.module.contents.desc=Gibt die Dokumentationsgranularität von Moduldeklarationen\nan. Mögliche Werte sind "api" oder "all". -main.opt.expand.requires.arg= +main.opt.expand.requires.arg=(transitive|all) main.opt.expand.requires.desc=Anweisungen im Tool zum Erweitern des zu dokumentierenden\nModulsets. Standardmäßig werden nur die Module dokumentiert,\ndie in der Befehlszeile ausdrücklich angegeben werden. Der Wert\n"transitive" schließt zusätzlich alle "requires transitive"-Abhängigkeiten\nder Module ein. Der Wert "all" schließt\nalle Abhängigkeiten der Module ein. main.opt.help.desc=Zeigt die Befehlszeilenoptionen an und beendet diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc_ja.properties b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc_ja.properties index 1cafe4d6ad5..42765ab4ded 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc_ja.properties +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc_ja.properties @@ -50,18 +50,18 @@ main.opt.package.desc=package/protected/publicタイプとメンバーを表示 main.opt.private.desc=すべてのタイプとメンバーを表示します。名前のあるモジュールの場合、\nすべてのパッケージとすべてのモジュール詳細を表示します。 main.opt.show.members.arg= -main.opt.show.members.desc=値が"public"、"protected"、"package"または"private"のいずれかの\nどのメンバー(フィールドやメソッドなど)をドキュメント化するかを指定する。\nデフォルトは"protected"で、publicおよびprotectedメンバーが表示され、\n"public"ではpublicメンバーのみが表示されます。"package"では\npublic、protectedおよびpackageメンバーが表示され、"private"\nではすべてのメンバーが表示されます。 +main.opt.show.members.desc=値が"public"、"protected"、"package"または"private"のいずれかの\nどのメンバー(フィールド、メソッドまたはコンストラクタ)をドキュメント化するかを指定する。\nデフォルトは"protected"で、publicおよびprotectedメンバーが表示され、\n"public"ではpublicメンバーのみが表示されます。"package"では\npublic、protectedおよびpackageメンバーが表示され、"private"\nではすべてのメンバーが表示されます。 main.opt.show.types.arg= main.opt.show.types.desc=値が"public"、"protected"、"package"または"private"のいずれかの\nどの型(クラスやインタフェースなど)をドキュメント化するかを指定する。\nデフォルトは"protected"で、publicおよびprotected型が表示され、\n"public"ではpublic型のみが表示されます。"package"では\npublic、protectedおよびpackage型が表示され、"private"\nではすべての型が表示されます。 main.opt.show.packages.arg= -main.opt.show.packages.desc=どのモジュールのパッケージをドキュメント化するかを指定する。使用可能な\n値は、"exported"または"all"パッケージです。 +main.opt.show.packages.desc=どのモジュール・パッケージをドキュメント化するかを指定する。使用可能な\n値は、"exported"または"all"パッケージです。 main.opt.show.module.contents.arg= main.opt.show.module.contents.desc=モジュール宣言のドキュメント化の粒度を指定する。\n使用可能な値は、"api"または"all"です。 -main.opt.expand.requires.arg= +main.opt.expand.requires.arg=(transitive|all) main.opt.expand.requires.desc=ドキュメント化するモジュールのセットを拡張するための\nツールを指定する。デフォルトでは、コマンドラインで明示的に\n指定されたモジュールのみがドキュメント化されます。"transitive"の値は、\nそれらのモジュールのすべての"requires transitive"依存性を追加で\n含めます。"all"の値は、それらのモジュールのすべての依存性を\n含めます。 main.opt.help.desc=コマンドライン・オプションを表示して終了する diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc_zh_CN.properties b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc_zh_CN.properties index 4ad91361e06..27053b44753 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc_zh_CN.properties +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc_zh_CN.properties @@ -50,18 +50,18 @@ main.opt.package.desc=显示程序包/受保护/公共类型和成员。对于 \ main.opt.private.desc=显示所有类型和成员。对于命名模块,\n显示所有程序包和所有模块详细信息。 main.opt.show.members.arg=<值> -main.opt.show.members.desc=指定将文档化的成员 (字段, 方法等), 其值可以\n为 "public", "protected", "package" 或 \n"private" 之一。默认值为 "protected", 该值将\n显示公共和受保护成员, "public" 将仅显示\n公共成员, "package" 将显示公共, 受保护和\n程序包成员, "private" 将显示所有成员。 +main.opt.show.members.desc=指定将文档化的成员(字段、方法或构造器),\n其值可以为 "public"、"protected"、"package" \n或 "private" 之一。默认值为 "protected",此时将\n显示公共和受保护成员,值为 "public" 时将仅显示\n公共成员,值为 "package" 时将显示公共、受保护\n和程序包成员,值为 "private" 时将显示所有成员。 main.opt.show.types.arg=<值> main.opt.show.types.desc=指定将文档化的类型 (类, 接口等), 其值可以\n为 "public", "protected", "package" 或 \n"private" 之一。默认值为 "protected", 该值将\n显示公共和受保护类型, "public" 将仅显示\n公共类型, "package" 将显示公共, 受保护和\n程序包类型, "private" 将显示所有类型。 main.opt.show.packages.arg=<值> -main.opt.show.packages.desc=指定将文档化的模块的程序包。\n可能的值为 "exported" 或 "all" 程序包。 +main.opt.show.packages.desc=指定将文档化的模块程序包。可能的\n值为 "exported" 或 "all" 程序包。 main.opt.show.module.contents.arg=<值> main.opt.show.module.contents.desc=指定模块声明的文档粒度。\n可能的值为 "api" 或 "all"。 -main.opt.expand.requires.arg=<值> +main.opt.expand.requires.arg=(transitive|all) main.opt.expand.requires.desc=指示工具展开要文档化的模块集。\n默认情况下, 将仅文档化命令行中明确\n指定的模块。值 "transitive" 将额外包含\n这些模块的所有 "requires transitive"\n被依赖对象。值 "all" 将包含这些模块\n的所有被依赖对象。 main.opt.help.desc=显示命令行选项并退出 diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/javap/resources/javap_de.properties b/src/jdk.jdeps/share/classes/com/sun/tools/javap/resources/javap_de.properties index 1c98b4cac6a..72cd09ee8fc 100644 --- a/src/jdk.jdeps/share/classes/com/sun/tools/javap/resources/javap_de.properties +++ b/src/jdk.jdeps/share/classes/com/sun/tools/javap/resources/javap_de.properties @@ -66,7 +66,7 @@ main.opt.version=\ -version Versionsinformationen main.opt.v=\ -v -verbose Gibt zusätzliche Informationen aus -main.opt.l=\ -l Gibt die Zeilennummer und lokale Variablentabellen aus +main.opt.l=\ -l Gibt die Zeilennummer und lokale Variablentabellen aus, kann zusammen mit "-c" verwendet werden main.opt.public=\ -public Zeigt nur öffentliche Klassen und Mitglieder diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/javap/resources/javap_ja.properties b/src/jdk.jdeps/share/classes/com/sun/tools/javap/resources/javap_ja.properties index 4cc9e83070d..89a9d3f5904 100644 --- a/src/jdk.jdeps/share/classes/com/sun/tools/javap/resources/javap_ja.properties +++ b/src/jdk.jdeps/share/classes/com/sun/tools/javap/resources/javap_ja.properties @@ -66,7 +66,7 @@ main.opt.version=\ -version バージョン情報 main.opt.v=\ -v -verbose 追加情報を出力する -main.opt.l=\ -l 行番号とローカル変数表を出力する +main.opt.l=\ -l 行番号とローカル変数表を出力する。-cとの組合せで動作します main.opt.public=\ -public publicクラスおよびメンバーのみを表示する diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/javap/resources/javap_zh_CN.properties b/src/jdk.jdeps/share/classes/com/sun/tools/javap/resources/javap_zh_CN.properties index 77c2fdd6b63..4d23376c7e3 100644 --- a/src/jdk.jdeps/share/classes/com/sun/tools/javap/resources/javap_zh_CN.properties +++ b/src/jdk.jdeps/share/classes/com/sun/tools/javap/resources/javap_zh_CN.properties @@ -66,7 +66,7 @@ main.opt.version=\ -version 版本信息 main.opt.v=\ -v -verbose 输出附加信息 -main.opt.l=\ -l 输出行号和本地变量表 +main.opt.l=\ -l 输出行号和本地变量表,与 -c 结合使用 main.opt.public=\ -public 仅显示公共类和成员 diff --git a/src/jdk.jfr/share/classes/jdk/jfr/FlightRecorder.java b/src/jdk.jfr/share/classes/jdk/jfr/FlightRecorder.java index 774b36b97d7..c3f97f0ff60 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/FlightRecorder.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/FlightRecorder.java @@ -249,8 +249,7 @@ public List getEventTypes() { } /** - * Adds a recorder listener and captures the {@code AccessControlContext} to - * use when invoking the listener. + * Adds a recorder listener. *

* If Flight Recorder is already initialized when the listener is added, then the method * {@link FlightRecorderListener#recorderInitialized(FlightRecorder)} method is diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecorder.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecorder.java index b33a8943042..bb2c8207cfe 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecorder.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecorder.java @@ -679,4 +679,8 @@ public synchronized void migrate(SafePath repo) throws IOException { public RepositoryChunk getCurrentChunk() { return currentChunk; } + + public synchronized void flush() { + MetadataRepository.getInstance().flush(); + } } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/periodic/FlushTask.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/periodic/FlushTask.java index 407bdadad43..739f32bf634 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/periodic/FlushTask.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/periodic/FlushTask.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,8 @@ import jdk.jfr.internal.JVM; import jdk.jfr.internal.MetadataRepository; +import jdk.jfr.internal.PlatformRecorder; +import jdk.jfr.internal.PrivateAccess; import jdk.jfr.internal.util.Utils; /** @@ -44,7 +46,8 @@ public FlushTask() { @Override public void execute(long timestamp, PeriodicType periodicType) { - MetadataRepository.getInstance().flush(); + PlatformRecorder recorder = PrivateAccess.getInstance().getPlatformRecorder(); + recorder.flush(); Utils.notifyFlush(); } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/query/FieldBuilder.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/query/FieldBuilder.java index c6916bc52ef..391db7cc930 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/query/FieldBuilder.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/query/FieldBuilder.java @@ -353,9 +353,10 @@ record WildcardElement(String name, String label, ValueDescriptor field) { var subFields = we.field().getFields().reversed(); if (!subFields.isEmpty() && !KNOWN_TYPES.contains(we.field().getTypeName())) { for (ValueDescriptor subField : subFields) { - String n = we.name + "." + subField.getName(); - String l = we.label + " : " + makeLabel(subField, false); - if (stack.size() < 2) { // Limit depth to 2 + // Limit depth to 2 + if (!we.name.contains(".")) { + String n = we.name + "." + subField.getName(); + String l = we.label + " : " + makeLabel(subField, false); stack.push(new WildcardElement(n, l, subField)); } } diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java index 0eda0b5d455..928b9a47934 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java @@ -49,7 +49,6 @@ import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.HashMap; @@ -278,14 +277,6 @@ int run(String[] args) { return EXIT_OK; } - if (options.modulePath.isEmpty()) { - // no --module-path specified - try to set $JAVA_HOME/jmods if that exists - Path jmods = getDefaultModulePath(); - if (jmods != null) { - options.modulePath.add(jmods); - } - } - JlinkConfiguration config = initJlinkConfig(); outputPath = config.getOutput(); if (options.suggestProviders) { @@ -378,42 +369,89 @@ public static void createImage(JlinkConfiguration config, // the token for "all modules on the module path" private static final String ALL_MODULE_PATH = "ALL-MODULE-PATH"; private JlinkConfiguration initJlinkConfig() throws BadArgs { - Set roots = new HashSet<>(); - for (String mod : options.addMods) { - if (mod.equals(ALL_MODULE_PATH) && options.modulePath.size() > 0) { - ModuleFinder finder = newModuleFinder(options.modulePath, options.limitMods, Set.of()); - // all observable modules are roots - finder.findAll() - .stream() - .map(ModuleReference::descriptor) - .map(ModuleDescriptor::name) - .forEach(mn -> roots.add(mn)); - } else { - roots.add(mod); - } + // Empty module path not allowed with ALL-MODULE-PATH in --add-modules + if (options.addMods.contains(ALL_MODULE_PATH) && options.modulePath.isEmpty()) { + throw taskHelper.newBadArgs("err.no.module.path"); } - - ModuleFinder finder = newModuleFinder(options.modulePath, options.limitMods, roots); - if (finder.find("java.base").isEmpty()) { + ModuleFinder appModuleFinder = newModuleFinder(options.modulePath); + ModuleFinder finder = appModuleFinder; + + boolean isLinkFromRuntime = false; + if (!appModuleFinder.find("java.base").isPresent()) { + // If the application module finder doesn't contain the + // java.base module we have one of two cases: + // 1. A custom module is being linked into a runtime, but the JDK + // modules have not been provided on the module path. + // 2. We have a run-time image based link. + // + // Distinguish case 2 by adding the default 'jmods' folder and try + // the look-up again. For case 1 this will now find java.base, but + // not for case 2, since the jmods folder is not there or doesn't + // include the java.base module. Path defModPath = getDefaultModulePath(); if (defModPath != null) { - options.modulePath.add(defModPath); + List combinedPaths = new ArrayList<>(options.modulePath); + combinedPaths.add(defModPath); + finder = newModuleFinder(combinedPaths); + } + // We've just added the default module path ('jmods'). If we still + // don't find java.base, we must resolve JDK modules from the + // current run-time image. + if (!finder.find("java.base").isPresent()) { + // If we don't have a linkable run-time image this is an error + if (!LinkableRuntimeImage.isLinkableRuntime()) { + throw taskHelper.newBadArgs("err.runtime.link.not.linkable.runtime"); + } + isLinkFromRuntime = true; + // JDK modules come from the system module path + finder = ModuleFinder.compose(ModuleFinder.ofSystem(), appModuleFinder); } - finder = newModuleFinder(options.modulePath, options.limitMods, roots); } - boolean isLinkFromRuntime = options.modulePath.isEmpty(); - // In case of custom modules outside the JDK we may - // have a non-empty module path, which must not include - // java.base. If it did, we link using packaged modules from that - // module path. If the module path does not include java.base, we have - // the case where we link from the run-time image. In that case, we take - // the JDK modules from the run-time image (ModuleFinder.ofSystem()). - if (finder.find("java.base").isEmpty()) { - isLinkFromRuntime = true; - ModuleFinder runtimeImageFinder = ModuleFinder.ofSystem(); - finder = combinedFinders(runtimeImageFinder, finder, options.limitMods, roots); + // Sanity check version if we use JMODs + if (!isLinkFromRuntime) { + checkJavaBaseVersion(finder); + } + + // Determine the roots set + Set roots = new HashSet<>(); + for (String mod : options.addMods) { + if (mod.equals(ALL_MODULE_PATH)) { + // Using --limit-modules with ALL-MODULE-PATH is an error + if (!options.limitMods.isEmpty()) { + throw taskHelper.newBadArgs("err.limit.modules"); + } + // all observable modules in the app module path are roots + Set initialRoots = appModuleFinder.findAll() + .stream() + .map(ModuleReference::descriptor) + .map(ModuleDescriptor::name) + .collect(Collectors.toSet()); + + // Error if no module is found on the app module path + if (initialRoots.isEmpty()) { + String modPath = options.modulePath.stream() + .map(a -> a.toString()) + .collect(Collectors.joining(", ")); + throw taskHelper.newBadArgs("err.empty.module.path", modPath); + } + + // Use a module finder with limited observability, as determined + // by initialRoots, to find the observable modules from the + // application module path (--module-path option) only. We must + // not include JDK modules from the default module path or the + // run-time image. + ModuleFinder mf = limitFinder(finder, initialRoots, Set.of()); + mf.findAll() + .stream() + .map(ModuleReference::descriptor) + .map(ModuleDescriptor::name) + .forEach(mn -> roots.add(mn)); + } else { + roots.add(mod); + } } + finder = limitFinder(finder, options.limitMods, roots); // --keep-packaged-modules doesn't make sense as we are not linking // from packaged modules to begin with. @@ -429,48 +467,13 @@ private JlinkConfiguration initJlinkConfig() throws BadArgs { options.generateLinkableRuntime); } - /** - * Creates a combined module finder of {@code finder} and - * {@code runtimeImageFinder} that first looks-up modules in the - * {@code runtimeImageFinder} and if not present in {@code finder}. - * - * @param runtimeImageFinder A system modules finder. - * @param finder A module finder based on packaged modules. - * @param limitMods The set of limited modules for the resulting - * finder (if any). - * @param roots All module roots. - * - * @return A combined finder, or the input finder, potentially applying - * module limits. + /* + * Creates a ModuleFinder for the given module paths. */ - private ModuleFinder combinedFinders(ModuleFinder runtimeImageFinder, - ModuleFinder finder, - Set limitMods, - Set roots) { - ModuleFinder combined = new ModuleFinder() { - - @Override - public Optional find(String name) { - Optional mref = runtimeImageFinder.find(name); - if (mref.isEmpty()) { - return finder.find(name); - } - return mref; - } - - @Override - public Set findAll() { - Set all = new HashSet<>(); - all.addAll(runtimeImageFinder.findAll()); - all.addAll(finder.findAll()); - return Collections.unmodifiableSet(all); - } - }; - // if limitmods is specified then limit the universe - if (limitMods != null && !limitMods.isEmpty()) { - return limitFinder(combined, limitMods, Objects.requireNonNull(roots)); - } - return combined; + public static ModuleFinder newModuleFinder(List paths) { + Runtime.Version version = Runtime.version(); + Path[] entries = paths.toArray(new Path[0]); + return ModulePath.of(version, true, entries); } private void createImage(JlinkConfiguration config) throws Exception { @@ -510,48 +513,81 @@ public static Path getDefaultModulePath() { } /* - * Returns a module finder of the given module path or the system modules - * if the module path is empty that limits the observable modules to those - * in the transitive closure of the modules specified in {@code limitMods} - * plus other modules specified in the {@code roots} set. + * Returns a module finder of the given module finder that limits the + * observable modules to those in the transitive closure of the modules + * specified in {@code limitMods} plus other modules specified in the + * {@code roots} set. + */ + public static ModuleFinder limitFinder(ModuleFinder finder, + Set limitMods, + Set roots) { + // if limitMods is specified then limit the universe + if (limitMods != null && !limitMods.isEmpty()) { + Objects.requireNonNull(roots); + // resolve all root modules + Configuration cf = Configuration.empty() + .resolve(finder, + ModuleFinder.of(), + limitMods); + + // module name -> reference + Map map = new HashMap<>(); + cf.modules().forEach(m -> { + ModuleReference mref = m.reference(); + map.put(mref.descriptor().name(), mref); + }); + + // add the other modules + roots.stream() + .map(finder::find) + .flatMap(Optional::stream) + .forEach(mref -> map.putIfAbsent(mref.descriptor().name(), mref)); + + // set of modules that are observable + Set mrefs = new HashSet<>(map.values()); + + return new ModuleFinder() { + @Override + public Optional find(String name) { + return Optional.ofNullable(map.get(name)); + } + + @Override + public Set findAll() { + return mrefs; + } + }; + } + return finder; + } + + /* + * Checks the version of the module descriptor of java.base for compatibility + * with the current runtime version. * - * @throws IllegalArgumentException if java.base module is present - * but its descriptor has no version + * @throws IllegalArgumentException the descriptor of java.base has no + * version or the java.base version is not the same as the current runtime's + * version. */ - public static ModuleFinder newModuleFinder(List paths, - Set limitMods, - Set roots) - { - Runtime.Version version = Runtime.version(); - Path[] entries = paths.toArray(new Path[0]); - ModuleFinder finder = paths.isEmpty() ? ModuleFinder.ofSystem() - : ModulePath.of(version, true, entries); - if (finder.find("java.base").isPresent()) { - // use the version of java.base module, if present, as - // the release version for multi-release JAR files - ModuleDescriptor.Version v = finder.find("java.base").get() + private static void checkJavaBaseVersion(ModuleFinder finder) { + assert finder.find("java.base").isPresent(); + + // use the version of java.base module, if present, as + // the release version for multi-release JAR files + ModuleDescriptor.Version v = finder.find("java.base").get() .descriptor().version().orElseThrow(() -> - new IllegalArgumentException("No version in java.base descriptor") - ); - - // java.base version is different than the current runtime version - version = Runtime.Version.parse(v.toString()); - if (Runtime.version().feature() != version.feature() || - Runtime.version().interim() != version.interim()) - { - // jlink version and java.base version do not match. - // We do not (yet) support this mode. - throw new IllegalArgumentException(taskHelper.getMessage("err.jlink.version.mismatch", + new IllegalArgumentException("No version in java.base descriptor") + ); + + Runtime.Version version = Runtime.Version.parse(v.toString()); + if (Runtime.version().feature() != version.feature() || + Runtime.version().interim() != version.interim()) { + // jlink version and java.base version do not match. + // We do not (yet) support this mode. + throw new IllegalArgumentException(taskHelper.getMessage("err.jlink.version.mismatch", Runtime.version().feature(), Runtime.version().interim(), version.feature(), version.interim())); - } } - - // if limitmods is specified then limit the universe - if (limitMods != null && !limitMods.isEmpty()) { - finder = limitFinder(finder, limitMods, Objects.requireNonNull(roots)); - } - return finder; } private static void deleteDirectory(Path dir) throws IOException { @@ -611,10 +647,6 @@ private static ImageHelper createImageProvider(JlinkConfiguration config, // Perform some sanity checks for linking from the run-time image if (config.linkFromRuntimeImage()) { - if (!LinkableRuntimeImage.isLinkableRuntime()) { - String msg = taskHelper.getMessage("err.runtime.link.not.linkable.runtime"); - throw new IllegalArgumentException(msg); - } // Do not permit linking from run-time image and also including jdk.jlink module if (cf.findModule(JlinkTask.class.getModule().getName()).isPresent()) { String msg = taskHelper.getMessage("err.runtime.link.jdk.jlink.prohibited"); @@ -773,49 +805,6 @@ private static String findModuleName(Path modInfoPath) { } } - /* - * Returns a ModuleFinder that limits observability to the given root - * modules, their transitive dependences, plus a set of other modules. - */ - public static ModuleFinder limitFinder(ModuleFinder finder, - Set roots, - Set otherMods) { - - // resolve all root modules - Configuration cf = Configuration.empty() - .resolve(finder, - ModuleFinder.of(), - roots); - - // module name -> reference - Map map = new HashMap<>(); - cf.modules().forEach(m -> { - ModuleReference mref = m.reference(); - map.put(mref.descriptor().name(), mref); - }); - - // add the other modules - otherMods.stream() - .map(finder::find) - .flatMap(Optional::stream) - .forEach(mref -> map.putIfAbsent(mref.descriptor().name(), mref)); - - // set of modules that are observable - Set mrefs = new HashSet<>(map.values()); - - return new ModuleFinder() { - @Override - public Optional find(String name) { - return Optional.ofNullable(map.get(name)); - } - - @Override - public Set findAll() { - return mrefs; - } - }; - } - private static Platform targetPlatform(Configuration cf, Map modsPaths, boolean runtimeImageLink) throws IOException { diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/runtimelink/JimageDiffGenerator.java b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/runtimelink/JimageDiffGenerator.java index 477bacfd6b5..3deb0ef577c 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/runtimelink/JimageDiffGenerator.java +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/runtimelink/JimageDiffGenerator.java @@ -4,7 +4,9 @@ * * 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. + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/runtimelink/ResourcePoolReader.java b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/runtimelink/ResourcePoolReader.java index 5a263eea814..c4c16579906 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/runtimelink/ResourcePoolReader.java +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/runtimelink/ResourcePoolReader.java @@ -4,7 +4,9 @@ * * 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. + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink.properties b/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink.properties index b5880a35561..a491b758ea0 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink.properties +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink.properties @@ -127,7 +127,9 @@ err.runtime.link.packaged.mods=This JDK has no packaged modules.\ err.runtime.link.modified.file={0} has been modified err.runtime.link.patched.module=jlink does not support linking from the run-time image\ \ when running on a patched runtime with --patch-module -err.empty.module.path=empty module path +err.no.module.path=--module-path option must be specified with --add-modules ALL-MODULE-PATH +err.empty.module.path=No module found in module path ''{0}'' with --add-modules ALL-MODULE-PATH +err.limit.modules=--limit-modules not allowed with --add-modules ALL-MODULE-PATH err.jlink.version.mismatch=jlink version {0}.{1} does not match target java.base version {2}.{3} err.automatic.module:automatic module cannot be used with jlink: {0} from {1} err.unknown.byte.order:unknown byte order {0} diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_de.properties b/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_de.properties index 833b56ee5f3..eebf34ce355 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_de.properties +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_de.properties @@ -62,10 +62,19 @@ main.msg.bug=Eine Ausnahme ist in jlink aufgetreten. Melden Sie in der Java-Bugd main.extended.help=Liste der verfügbaren Plug-ins: main.extended.help.footer=Bei Optionen, die eine erfordern, ist der Wert eine kommagetrennte\nListe von Elementen, die jeweils eines der folgenden Formate verwenden:\n \n glob:\n regex:\n @, wobei der Dateiname der Name einer Datei mit zu verwendenden Mustern ist,\n ein Muster pro Zeile\n\n +main.runtime.image.linking.cap.enabled=aktiviert +main.runtime.image.linking.cap.disabled=deaktiviert +main.runtime.image.linking.cap.sect.header=Funktionen: +main.runtime.image.linking.cap.msg=\ Assemblierung von Laufzeitimage {0} error.prefix=Fehler: warn.prefix=Warnung: +err.runtime.link.not.linkable.runtime=Dieses JDK unterstützt keine Assemblierung vom aktuellen Laufzeitimage +err.runtime.link.jdk.jlink.prohibited=Dieses JDK enthält keine als Pakete verpackten Module und kann nicht verwendet werden, um ein anderes Image mit dem Modul jdk.jlink zu erstellen +err.runtime.link.packaged.mods=Dieses JDK enthält keine als Pakete verpackten Module. "--keep-packaged-modules" wird nicht unterstützt +err.runtime.link.modified.file={0} wurde modifiziert +err.runtime.link.patched.module=Datei {0} nicht im Modulimage gefunden. "--patch-module" wird beim Verknüpfen aus dem Laufzeitimage nicht unterstützt err.empty.module.path=leerer Modulpfad err.jlink.version.mismatch=jlink-Version {0}.{1} stimmt nicht mit Ziel-java.base-Version {2}.{3} überein err.automatic.module:automatisches Modul kann nicht mit jlink verwendet werden: {0} aus {1} @@ -74,7 +83,7 @@ err.launcher.main.class.empty:Launcher-Hauptklassenname darf nicht leer sein: {0 err.launcher.module.name.empty:Launcher-Modulname darf nicht leer sein: {0} err.launcher.value.format:Launcher-Wert muss folgendes Format haben: =[/]: {0} err.output.must.be.specified:--output muss angegeben werden -err.modulepath.must.be.specified:--module-path ist nicht angegeben, und dieses Laufzeitimage enthält nicht das jmods-Verzeichnis. +err.modulepath.must.be.specified:"--module-path" ist nicht angegeben, und dieses Laufzeitimage enthält kein jmods-Verzeichnis err.mods.must.be.specified:keine Module zum {0} angegeben err.path.not.found=Pfad nicht gefunden: {0} err.path.not.valid=ungültiger Pfad: {0} @@ -106,3 +115,6 @@ warn.provider.notfound=Kein Provider für Service angegeben für --suggest-provi no.suggested.providers=Option --bind-services ist angegeben. Keine weiteren Provider vorgeschlagen. suggested.providers.header=Vorgeschlagene Provider providers.header=Provider + +runtime.link.info=Assemblierung basierend auf dem aktuellen Laufzeitimage +runtime.link.jprt.path.extra=(Laufzeitimage) diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_ja.properties b/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_ja.properties index e54e62bafed..a20a97bcfcb 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_ja.properties +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_ja.properties @@ -62,10 +62,19 @@ main.msg.bug=jlinkで例外が発生しました。データベースで重複 main.extended.help=使用可能なプラグインのリスト: main.extended.help.footer=を必要とするオプションの場合、値は、次の形式のいずれかを使用する、要素のカンマ区切りリストになります:\n \n glob:\n regex:\n @ filenameは、使用するパターンを含むファイル(1行ごとに1パターン)の名前です\n\n +main.runtime.image.linking.cap.enabled=有効 +main.runtime.image.linking.cap.disabled=無効 +main.runtime.image.linking.cap.sect.header=機能: +main.runtime.image.linking.cap.msg=\ ランタイム・イメージ{0}からのリンク error.prefix=エラー: warn.prefix=警告: +err.runtime.link.not.linkable.runtime=このJDKでは、現在のランタイム・イメージからのリンクをサポートしていません +err.runtime.link.jdk.jlink.prohibited=このJDKは、パッケージ化されたモジュールを含んでおらず、jdk.jlinkモジュールによる別のイメージの作成に使用できません +err.runtime.link.packaged.mods=このJDKにはパッケージ化されたモジュールがありません。--keep-packaged-modulesはサポートされていません +err.runtime.link.modified.file={0}が変更されました +err.runtime.link.patched.module=ファイル{0}がモジュール・イメージに見つかりません。ランタイム・イメージからリンクする際、--patch-moduleはサポートされていません err.empty.module.path=空のモジュール・パス err.jlink.version.mismatch=jlinkバージョン{0}.{1}がターゲットのjava.baseバージョン{2}.{3}と一致しません err.automatic.module:jlinkでは自動モジュールは使用できません: {1}からの{0} @@ -74,7 +83,7 @@ err.launcher.main.class.empty:起動ツールのメイン・クラス名は空 err.launcher.module.name.empty:起動ツールのモジュール名は空にできません: {0} err.launcher.value.format:起動ツールの値は=[/]の形式にしてください: {0} err.output.must.be.specified:--outputを指定する必要があります -err.modulepath.must.be.specified:--module-pathが指定されておらず、このランタイム・イメージにjmodsディレクトリが含まれていません。 +err.modulepath.must.be.specified:--module-pathが指定されておらず、このランタイム・イメージにjmodsディレクトリが含まれていません err.mods.must.be.specified:{0}にモジュールが指定されていません err.path.not.found=パスが見つかりません: {0} err.path.not.valid=無効なパス: {0} @@ -106,3 +115,6 @@ warn.provider.notfound=--suggest-providersに指定されたサービスにプ no.suggested.providers=--bind-servicesオプションが指定されています。追加のプロバイダは推奨されません。 suggested.providers.header=推奨プロバイダ providers.header=プロバイダ + +runtime.link.info=現在のランタイム・イメージに基づいてリンク +runtime.link.jprt.path.extra=(ランタイム・イメージ) diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_zh_CN.properties b/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_zh_CN.properties index 9c44e826b93..c6746c7705c 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_zh_CN.properties +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_zh_CN.properties @@ -62,10 +62,19 @@ main.msg.bug=jlink 中出现异常错误。如果在 Java Bug Database (https:// main.extended.help=可用插件列表: main.extended.help.footer=对于需要 <模式列表> 的选项, 值将为逗号分隔的元素列表, 每个元素使用以下格式之一:\n \n glob:\n regex:<正则表达式模式>\n @<文件名>, 其中“文件名”是包含要使用的模式的文件名, 每行一个模式\n\n +main.runtime.image.linking.cap.enabled=启用 +main.runtime.image.linking.cap.disabled=禁用 +main.runtime.image.linking.cap.sect.header=功能: +main.runtime.image.linking.cap.msg=\ 从运行时映像 {0} 链接 error.prefix=错误: warn.prefix=警告: +err.runtime.link.not.linkable.runtime=此 JDK 不支持从当前运行时映像链接 +err.runtime.link.jdk.jlink.prohibited=此 JDK 不包含打包模块,无法用于使用 jdk.jlink 模块创建其他映像 +err.runtime.link.packaged.mods=此 JDK 没有打包模块。不支持 --keep-packaged-modules +err.runtime.link.modified.file=已修改 {0} +err.runtime.link.patched.module=在模块映像中未找到文件 {0}。从运行时映像链接时,不支持 --patch-module err.empty.module.path=空模块路径 err.jlink.version.mismatch=jlink 版本 {0}.{1} 与目标 java.base 版本 {2}.{3} 不匹配 err.automatic.module:自动模块不能用于来自 {1} 的 jlink: {0} @@ -74,7 +83,7 @@ err.launcher.main.class.empty:启动程序主类名不能为空: {0} err.launcher.module.name.empty:启动程序模块名称不能为空: {0} err.launcher.value.format:启动程序值应使用“<命令>=<模块>[/<主类>]”格式: {0} err.output.must.be.specified:必须指定 --output -err.modulepath.must.be.specified:未指定 --module-path,此运行时映像不包含 jmods 目录。 +err.modulepath.must.be.specified:未指定 --module-path,此运行时映像不包含 jmods 目录 err.mods.must.be.specified:没有将任何模块指定到{0} err.path.not.found=找不到路径: {0} err.path.not.valid=无效路径: {0} @@ -106,3 +115,6 @@ warn.provider.notfound=找不到为 --suggest-providers 指定的服务提供方 no.suggested.providers=指定了 --bind-services 选项。未建议其他提供方。 suggested.providers.header=建议的提供方 providers.header=提供方 + +runtime.link.info=基于当前运行时映像进行链接 +runtime.link.jprt.path.extra=(运行时映像) diff --git a/src/jdk.jlink/share/classes/jdk/tools/jmod/resources/jmod_ja.properties b/src/jdk.jlink/share/classes/jdk/tools/jmod/resources/jmod_ja.properties index 980c8eb2316..b346d3cde82 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jmod/resources/jmod_ja.properties +++ b/src/jdk.jlink/share/classes/jdk/tools/jmod/resources/jmod_ja.properties @@ -96,8 +96,8 @@ err.module.resolution.fail=解決に失敗しました: {0} err.no.moduleToHash=ハッシュが記録されていません: {0}に一致し、ハッシュを記録するモジュールが見つかりません err.invalid.date=--date {0}は、オプションのタイムゾーン書式: {1}を指定した、有効なISO-8601の拡張オフセットの日時ではありません err.date.out.of.range=--date {0}は有効な範囲1980-01-01T00:00:02Zから2099-12-31T23:59:59Zにありません -err.compress.incorrect=--圧縮値が無効です: {0} -err.compress.wrong.mode=--圧縮を行えるのは作成モードのときのみです +err.compress.incorrect=--compress値が無効です: {0} +err.compress.wrong.mode=--compressを行えるのは作成モードのときのみです warn.invalid.arg=無効なクラス名またはパス名が存在しません: {0} warn.no.module.hashes=ハッシュが記録されていません: {0}に依存するハッシュに対してモジュールが指定されていません warn.ignore.entry=セクション{1}のエントリ{0}を無視します diff --git a/src/jdk.jlink/share/classes/jdk/tools/jmod/resources/jmod_zh_CN.properties b/src/jdk.jlink/share/classes/jdk/tools/jmod/resources/jmod_zh_CN.properties index 409081fc45b..1cf9d001fa3 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jmod/resources/jmod_zh_CN.properties +++ b/src/jdk.jlink/share/classes/jdk/tools/jmod/resources/jmod_zh_CN.properties @@ -96,8 +96,8 @@ err.module.resolution.fail=解析失败: {0} err.no.moduleToHash=未记录散列:找不到与 {0} 匹配的模块来记录散列 err.invalid.date=--date {0} 不是具有可选时区的有效 ISO-8601 扩展偏移日期时间格式:{1} err.date.out.of.range=--date {0} 不在 1980-01-01T00:00:02Z 到 2099-12-31T23:59:59Z 这一有效范围内 -err.compress.incorrect=--压缩值无效:{0} -err.compress.wrong.mode=--仅在使用创建模式时接受压缩 +err.compress.incorrect=--compress 值无效:{0} +err.compress.wrong.mode=仅在使用创建模式时接受 --compress warn.invalid.arg=类名无效或路径名不存在: {0} warn.no.module.hashes=未记录任何散列: 没有为依赖于 {0} 的散列处理指定模块 warn.ignore.entry=正在忽略节 {1} 中的条目 {0} diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_de.properties b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_de.properties index c0aece573e0..f76d3a3743f 100644 --- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_de.properties +++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_de.properties @@ -93,6 +93,6 @@ message.signing.pkg=Warnung: Zum Signieren von PKG müssen Sie möglicherweise m message.setfile.dmg=Das Festlegen des benutzerdefinierten Symbols für die DMG-Datei wurde übersprungen, weil das Utility "SetFile" nicht gefunden wurde. Durch Installieren von Xcode mit Befehlszeilentools sollte dieses Problem behoben werden. message.install-dir-ignored=Warnung: "--install-dir" wird von DMG nicht unterstützt. Stattdessen wird standardmäßig /Applications verwendet. message.codesign.failed.reason.app.content="codesign" war nicht erfolgreich, und zusätzlicher Anwendungsinhalt wurde über den Parameter "--app-content" angegeben. Wahrscheinlich hat der zusätzliche Inhalt die Integrität des Anwendungs-Bundles beeinträchtigt und den Fehler verursacht. Stellen Sie sicher, das der über den Parameter "--app-content" angegebene Inhalt nicht die Integrität des Anwendungs-Bundles beeinträchtigt, oder fügen Sie ihn im Nachverarbeitungsschritt hinzu. -message.codesign.failed.reason.xcode.tools=Possible reason for "codesign" failure is missing Xcode with command line developer tools. Install Xcode with command line developer tools to see if it resolves the problem. +message.codesign.failed.reason.xcode.tools=Möglicher Grund für "codesign"-Fehler ist fehlender Xcode mit Befehlszeilen-Entwicklertools. Installieren Sie Xcode mit Befehlszeilen-Entwicklertools, und prüfen Sie, ob das Problem dadurch beseitigt wird. warning.unsigned.app.image=Warnung: Nicht signiertes app-image wird zum Erstellen von signiertem {0} verwendet. warning.per.user.app.image.signed=Warnung: Konfiguration der installierten Anwendung pro Benutzer wird nicht unterstützt, da "{0}" im vordefinierten signierten Anwendungsimage fehlt. diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_ja.properties b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_ja.properties index 166e7ffb670..5ea13254e93 100644 --- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_ja.properties +++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_ja.properties @@ -93,6 +93,6 @@ message.signing.pkg=警告: PKGへの署名の場合、「キーチェーン・ message.setfile.dmg='SetFile'ユーティリティが見つからないため、DMGファイルでのカスタム・アイコンの設定がスキップされました。Xcodeとコマンド・ライン・ツールをインストールすると、この問題は解決されます。 message.install-dir-ignored=警告: "--install-dir"はDMGでサポートされていません。/Applicationsにデフォルト設定されます。 message.codesign.failed.reason.app.content="codesign"が失敗したため、追加のアプリケーション・コンテンツが、"--app-content"パラメータを介して提供されました。追加のコンテンツにより、アプリケーション・バンドルの整合性が損われ、失敗の原因になった可能性があります。"--app-content"パラメータを介して提供されたコンテンツによって、アプリケーション・バンドルの整合性が損われていないことを確認するか、処理後のステップで追加してください。 -message.codesign.failed.reason.xcode.tools=Possible reason for "codesign" failure is missing Xcode with command line developer tools. Install Xcode with command line developer tools to see if it resolves the problem. +message.codesign.failed.reason.xcode.tools="codesign"失敗の考えられる理由は、Xcodeとコマンドライン・デベロッパ・ツールの欠落です。Xcodeとコマンドライン・デベロッパ・ツールをインストールして、問題が解決されるかを確認してください。 warning.unsigned.app.image=警告: 署名されていないapp-imageを使用して署名された{0}を作成します。 warning.per.user.app.image.signed=警告: 事前定義済の署名付きアプリケーション・イメージに"{0}"がないため、インストール済アプリケーションのユーザーごとの構成はサポートされません。 diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_zh_CN.properties b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_zh_CN.properties index a620e8dacdd..1a262f461ac 100644 --- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_zh_CN.properties +++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_zh_CN.properties @@ -93,6 +93,6 @@ message.signing.pkg=警告:要对 PKG 进行签名,可能需要使用“密 message.setfile.dmg=由于未找到 'SetFile' 实用程序,跳过了针对 DMG 文件设置定制图标的操作。安装带命令行工具的 Xcode 应能解决此问题。 message.install-dir-ignored=警告:"--install-dir" 不受 DMG 支持,将默认为 /Applications。 message.codesign.failed.reason.app.content="codesign" 失败,并通过 "--app-content" 参数提供了附加应用程序内容。可能是附加内容破坏了应用程序包的完整性,导致了故障。请确保通过 "--app-content" 参数提供的内容不会破坏应用程序包的完整性,或者在后处理步骤中添加该内容。 -message.codesign.failed.reason.xcode.tools=Possible reason for "codesign" failure is missing Xcode with command line developer tools. Install Xcode with command line developer tools to see if it resolves the problem. +message.codesign.failed.reason.xcode.tools="codesign" 失败可能是因为缺少带命令行开发人员工具的 Xcode。请安装带命令行开发人员工具的 Xcode,看看是否可以解决问题。 warning.unsigned.app.image=警告:使用未签名的 app-image 生成已签名的 {0}。 warning.per.user.app.image.signed=警告:由于预定义的已签名应用程序映像中缺少 "{0}",不支持对已安装应用程序的每用户配置提供支持。 diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/PrettyPrintHandler.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/PrettyPrintHandler.java index ffd5b764103..1fb7c7ff7da 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/PrettyPrintHandler.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/PrettyPrintHandler.java @@ -4,7 +4,9 @@ * * 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. + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/XmlConsumer.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/XmlConsumer.java index 429be6aba05..a77c93e9383 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/XmlConsumer.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/XmlConsumer.java @@ -4,7 +4,9 @@ * * 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. + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/XmlUtils.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/XmlUtils.java index ff4168e5d0c..57ad1759bf4 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/XmlUtils.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/XmlUtils.java @@ -4,7 +4,9 @@ * * 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. + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ExceptionBox.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ExceptionBox.java index 55f2964445f..8428d5d1e7f 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ExceptionBox.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ExceptionBox.java @@ -4,7 +4,9 @@ * * 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. + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingBiConsumer.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingBiConsumer.java index e5b7704a92e..3ed0fd67d84 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingBiConsumer.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingBiConsumer.java @@ -4,7 +4,9 @@ * * 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. + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingBiFunction.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingBiFunction.java index a8119f25bdb..8c2df773eb5 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingBiFunction.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingBiFunction.java @@ -4,7 +4,9 @@ * * 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. + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingConsumer.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingConsumer.java index 5ca33c22d92..ef1b0a61df7 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingConsumer.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingConsumer.java @@ -4,7 +4,9 @@ * * 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. + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingFunction.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingFunction.java index db6b1d26005..2b5eae43842 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingFunction.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingFunction.java @@ -4,7 +4,9 @@ * * 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. + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingRunnable.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingRunnable.java index 7f3fcda536c..7c75c4d9753 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingRunnable.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingRunnable.java @@ -4,7 +4,9 @@ * * 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. + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingSupplier.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingSupplier.java index 2f5ef135875..c69c4729190 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingSupplier.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingSupplier.java @@ -4,7 +4,9 @@ * * 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. + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingUnaryOperator.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingUnaryOperator.java index 27a3e2f30f5..7a2a0fd67cf 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingUnaryOperator.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingUnaryOperator.java @@ -4,7 +4,9 @@ * * 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. + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_de.properties b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_de.properties index dce8ca6176d..31a0ebeab24 100644 --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_de.properties +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_de.properties @@ -40,9 +40,9 @@ resource.overrides-wix-file=Überschreibt WiX-Projektdatei resource.shortcutpromptdlg-wix-file=Dialogfeld für Verknüpfungs-Prompt der WiX-Projektdatei resource.installdirnotemptydlg-wix-file=Nicht leeres Installationsverzeichnis in Dialogfeld für WiX-Projektdatei resource.launcher-as-service-wix-file=WiX-Projektdatei für Serviceinstallationsprogramm -resource.wix-src-conv=XSLT stylesheet converting WiX sources from WiX v3 to WiX v4 format +resource.wix-src-conv=XSLT-Stylesheet zum Konvertieren von WiX-Quellen vom Format WiX v3 in WiX v4 -error.no-wix-tools=Can not find WiX tools. Was looking for WiX v3 light.exe and candle.exe or WiX v4/v5 wix.exe and none was found +error.no-wix-tools=WiX-Tools nicht gefunden. Gesucht wurden WiX v3 light.exe und candle.exe oder WiX v4/v5 wix.exe, aber keine der Dateien wurde gefunden error.no-wix-tools.advice=Laden Sie WiX 3.0 oder höher von https://wixtoolset.org herunter, und fügen Sie es zu PATH hinzu. error.version-string-wrong-format.advice=Setzen Sie den Wert des --app-version-Parameters auf eine gültige ProductVersion des Windows-Installationsprogramms. error.msi-product-version-components=Versionszeichenfolge [{0}] muss zwischen 2 und 4 Komponenten aufweisen. @@ -56,7 +56,7 @@ error.lock-resource=Sperren nicht erfolgreich: {0} error.unlock-resource=Aufheben der Sperre nicht erfolgreich: {0} error.read-wix-l10n-file=Datei {0} konnte nicht geparst werden error.extract-culture-from-wix-l10n-file=Kulturwert konnte nicht aus Datei {0} gelesen werden -error.short-path-conv-fail=Failed to get short version of "{0}" path +error.short-path-conv-fail=Kurze Version des Pfades "{0}" konnte nicht abgerufen werden message.icon-not-ico=Das angegebene Symbol "{0}" ist keine ICO-Datei und wird nicht verwendet. Stattdessen wird das Standardsymbol verwendet. message.potential.windows.defender.issue=Warnung: Windows Defender verhindert eventuell die korrekte Ausführung von jpackage. Wenn ein Problem auftritt, deaktivieren Sie das Echtzeitmonitoring, oder fügen Sie einen Ausschluss für das Verzeichnis "{0}" hinzu. diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_ja.properties b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_ja.properties index 47e5b585869..57391db9087 100644 --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_ja.properties +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_ja.properties @@ -40,9 +40,9 @@ resource.overrides-wix-file=WiXプロジェクト・ファイルのオーバー resource.shortcutpromptdlg-wix-file=ショートカット・プロンプト・ダイアログWiXプロジェクト・ファイル resource.installdirnotemptydlg-wix-file=インストール・ディレクトリ・ダイアログのWiXプロジェクト・ファイルが空ではありません resource.launcher-as-service-wix-file=サービス・インストーラWiXプロジェクト・ファイル -resource.wix-src-conv=XSLT stylesheet converting WiX sources from WiX v3 to WiX v4 format +resource.wix-src-conv=WiXソースをWiX v3からWiX v4フォーマットに変換するXSLTスタイルシート -error.no-wix-tools=Can not find WiX tools. Was looking for WiX v3 light.exe and candle.exe or WiX v4/v5 wix.exe and none was found +error.no-wix-tools=WiXツールが見つかりません。WiX v3 light.exeとcandle.exeまたはWiX v4/v5 wix.exeを探しましたが、いずれも見つかりませんでした error.no-wix-tools.advice=WiX 3.0以降をhttps://wixtoolset.orgからダウンロードし、PATHに追加します。 error.version-string-wrong-format.advice=--app-versionパラメータの値を有効なWindows Installer ProductVersionに設定します。 error.msi-product-version-components=バージョン文字列[{0}]には、2から4つのコンポーネントが含まれている必要があります。 @@ -56,7 +56,7 @@ error.lock-resource=ロックに失敗しました: {0} error.unlock-resource=ロック解除に失敗しました: {0} error.read-wix-l10n-file={0}ファイルの解析に失敗しました error.extract-culture-from-wix-l10n-file={0}ファイルからのカルチャの値の読取りに失敗しました -error.short-path-conv-fail=Failed to get short version of "{0}" path +error.short-path-conv-fail="{0}"パスの短縮バージョンの取得に失敗しました message.icon-not-ico=指定したアイコン"{0}"はICOファイルではなく、使用されません。デフォルト・アイコンがその位置に使用されます。 message.potential.windows.defender.issue=警告: Windows Defenderが原因でjpackageが機能しないことがあります。問題が発生した場合は、リアルタイム・モニタリングを無効にするか、ディレクトリ"{0}"の除外を追加することにより、問題に対処できます。 diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_zh_CN.properties b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_zh_CN.properties index abd3d13a667..bd93fc5951e 100644 --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_zh_CN.properties +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_zh_CN.properties @@ -40,9 +40,9 @@ resource.overrides-wix-file=覆盖 WiX 项目文件 resource.shortcutpromptdlg-wix-file=快捷方式提示对话框 WiX 项目文件 resource.installdirnotemptydlg-wix-file=安装目录对话框 WiX 项目文件非空 resource.launcher-as-service-wix-file=服务安装程序 WiX 项目文件 -resource.wix-src-conv=XSLT stylesheet converting WiX sources from WiX v3 to WiX v4 format +resource.wix-src-conv=将 WiX 源码从 WiX v3 格式转换为 WiX v4 格式的 XSLT 样式表 -error.no-wix-tools=Can not find WiX tools. Was looking for WiX v3 light.exe and candle.exe or WiX v4/v5 wix.exe and none was found +error.no-wix-tools=找不到 WiX 工具。已查找 WiX v3 light.exe 和 candle.exe 或 WiX v4/v5 wix.exe,但都未找到 error.no-wix-tools.advice=从 https://wixtoolset.org 下载 WiX 3.0 或更高版本,然后将其添加到 PATH。 error.version-string-wrong-format.advice=将 --app-version 参数的值设置为有效的 Windows Installer ProductVersion。 error.msi-product-version-components=版本字符串 [{0}] 必须包含 2 到 4 个组成部分。 @@ -56,7 +56,7 @@ error.lock-resource=无法锁定:{0} error.unlock-resource=无法解锁:{0} error.read-wix-l10n-file=无法解析 {0} 文件 error.extract-culture-from-wix-l10n-file=无法从 {0} 文件读取文化值 -error.short-path-conv-fail=Failed to get short version of "{0}" path +error.short-path-conv-fail=无法获取简短形式的 "{0}" 路径 message.icon-not-ico=指定的图标 "{0}" 不是 ICO 文件, 不会使用。将使用默认图标代替。 message.potential.windows.defender.issue=警告:Windows Defender 可能会阻止 jpackage 正常工作。如果存在问题,可以通过禁用实时监视或者为目录 "{0}" 添加排除项来解决。 diff --git a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n_de.properties b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n_de.properties index 21f30891008..b102638815c 100644 --- a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n_de.properties +++ b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n_de.properties @@ -180,7 +180,7 @@ jshell.console.empty = \nLeerer Eintrag. Ein einzelner gültiger Ausdruck oder e jshell.fix.wrong.shortcut =Unerwartetes Zeichen nach Umschalt+Tab.\nVerwenden Sie "I" für automatischen Import, "V" zur Variablenerstellung oder "M" zur Methodenerstellung.\nWeitere Informationen finden Sie unter:\n/help shortcuts -help.usage = Verwendung: jshell

+ * For the sake of brevity, to run all of these checkers use + *

+ * `make test-docs_all TEST_DEPS=docs-jdk` + *

+ * This collection of tests provide a variety of checks for JDK documentation bundle. + *

+ * It is meant to provide a convenient way to alert users of any errors in their documentation + * before a push and verify the quality of the documentation. + * It is not meant to replace more authoritative checkers; instead, + * it is more focused on providing a convenient, easy overview of any possible issues. + *

+ * It supports the following checks: + *

+ * *HTML* -- We use the standard `tidy` utility to check for HTML compliance, + * according to the declared version of HTML. + * The output from `tidy` is analysed to generate a report summarizing any issues that were found. + *

+ * Version `5.9.20` of `tidy` is expected, or the output from the `--version` option should contain the string `version 5`. + * The test warns the user if he is using an earlier version. + *

+ * *Bad Characters* -- We assumee that HTML files are encoded in UTF-8, + * and reports any character encoding issues that it finds. + *

+ * *DocType* -- We assume that HTML files should use HTML5, and reports + * any files for which that is not the case. + *

+ * *Links* -- We check links within a set of files, and reports on links + * to external resources, without otherwise checking them. + *

+ * *External Links* -- We scan the files for URLs that refer to + * external resources, and validates those references using a "golden file" that includes a list of vetted links. + *

+ * Each external reference is only checked once; but if an issue is found, all the files containing the + * reference will be reported. + */ +public class DocCheck extends TestRunner { + + private static final String DOCCHECK_DIR = System.getProperty("doccheck.dir"); + private static final Path DIR = Path.of(DOCCHECK_DIR != null ? DOCCHECK_DIR : ""); + private static final Set CHECKS_LIST = new HashSet<>(); + private static Path DOCS_DIR; + + private static boolean html; + private static boolean links; + private static boolean badchars; + private static boolean doctype; + private static boolean extlinks; + + private List files; + + public DocCheck() { + super(System.err); + init(); + } + + public static void main(String... args) throws Exception { + chooseCheckers(); + DocCheck docCheck = new DocCheck(); + docCheck.runTests(); + } + + private static void chooseCheckers() { + final String checks = System.getProperty("doccheck.checks"); + + if (!checks.isEmpty()) { + if (checks.contains(",")) { + CHECKS_LIST.addAll(Arrays.asList(checks.split(","))); + } else { + CHECKS_LIST.add(checks); + } + } + + if (CHECKS_LIST.contains("all")) { + html = true; + links = true; + badchars = true; + doctype = true; + extlinks = true; + } else { + if (CHECKS_LIST.contains("html")) { + html = true; + } + if (CHECKS_LIST.contains("links")) { + links = true; + } + if (CHECKS_LIST.contains("badchars")) { + badchars = true; + } + if (CHECKS_LIST.contains("doctype")) { + doctype = true; + } + if (CHECKS_LIST.contains("extlinks")) { + extlinks = true; + } + } + } + + public void init() { + var fileTester = new FileProcessor(); + DOCS_DIR = DocTester.resolveDocs(); + var baseDir = DOCS_DIR.resolve(DIR); + fileTester.processFiles(baseDir); + files = fileTester.getFiles(); + } + + public List getCheckers() { + + List checkers = new ArrayList<>(); + if (html) { + checkers.add(new TidyChecker()); + } + if (links) { + var linkChecker = new LinkChecker(); + linkChecker.setBaseDir(DOCS_DIR); + checkers.add(new HtmlFileChecker(linkChecker, DOCS_DIR)); + } + + if (extlinks) { + checkers.add(new HtmlFileChecker(new ExtLinkChecker(), DOCS_DIR)); + } + + // there should be almost nothing reported from these two checkers + // most reports should be broken anchors/links, missing files and errors in html + if (badchars) { + checkers.add(new BadCharacterChecker()); + } + if (doctype) { + checkers.add(new HtmlFileChecker(new DocTypeChecker(), DOCS_DIR)); + } + + return checkers; + } + + @Test + public void test() throws Exception { + List checkers = getCheckers(); + runCheckersSequentially(checkers); + } + + private void runCheckersSequentially(List checkers) throws Exception { + List exceptions = new ArrayList<>(); + + for (FileChecker checker : checkers) { + try (checker) { + checker.checkFiles(files); + } catch (Exception e) { + exceptions.add(e); + } + } + + if (!exceptions.isEmpty()) { + throw new Exception("One or more HTML checkers failed: " + exceptions); + } + } +} diff --git a/test/docs/jdk/javadoc/doccheck/ExtLinksJdk.txt b/test/docs/jdk/javadoc/doccheck/ExtLinksJdk.txt new file mode 100644 index 00000000000..704bdffb283 --- /dev/null +++ b/test/docs/jdk/javadoc/doccheck/ExtLinksJdk.txt @@ -0,0 +1,773 @@ +# This file is used to check external links in the JDK generated documentation +# to prevent broken links from backsliding into the JDK source. +# +# The file serves as a "whitelist" of links that have been checked to be working as intended +# and JDK developers should add external links to this file whenever they add them to their documentation. +# +# +# The links in this file are checked before every release. +# +# +# +http://cldr.unicode.org/ +http://csrc.nist.gov/publications/fips/fips186-3/fips_186-3.pdf +http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf +http://docs.oracle.com/javase/feedback.html +http://docs.oracle.com/javase/jndi/tutorial/index.html +http://docs.oracle.com/javase/specs/jls/se@@JAVASE_VERSION@@/html/jls-12.html +http://docs.oracle.com/javase/tutorial/collections/index.html +http://docs.oracle.com/javase/tutorial/i18n/format/decimalFormat.html +http://docs.oracle.com/javase/tutorial/i18n/format/simpleDateFormat.html +http://docs.oracle.com/javase/tutorial/jdbc/ +http://docs.oracle.com/javase/tutorial/jdbc/basics/index.html +http://docs.oracle.com/javase/tutorial/jdbc/basics/rowset.html +http://docs.oracle.com/javase/tutorial/uiswing/dnd/index.html +http://en.wikipedia.org/wiki/Skip_list +http://jclark.com/xml/xmlns.htm +http://jcp.org/en/jsr/detail?id=173 +http://jcp.org/en/jsr/detail?id=268 +http://relaxng.org/spec-20011203.html +http://sax.sourceforge.net/?selected=get-set +http://standards.iso.org/iso/9075/2002/12/sqlxml.xsd +http://svn.python.org/projects/python/trunk/Objects/listsort.txt +http://tools.ietf.org/html/rfc1421 +http://tools.ietf.org/html/rfc5869 +http://unicode.org/reports/tr35/ +http://unicode.org/reports/tr35/tr35-numbers.html +http://web.archive.org/web/20051219043731/http://archive.ncsa.uiuc.edu/SDG/Software/Mosaic/Demo/url-primer.html +http://www.cl.cam.ac.uk/~mgk25/time/utc-sls/ +http://www.cs.rochester.edu/~scott/papers/1996_PODC_queues.pdf +http://www.iana.org/ +http://www.iana.org/assignments/character-sets +http://www.iana.org/assignments/character-sets/character-sets.xhtml +http://www.iana.org/assignments/media-types/ +http://www.iana.org/assignments/uri-schemes.html +http://www.ietf.org/ +http://www.ietf.org/rfc/rfc0793.txt +http://www.ietf.org/rfc/rfc0822.txt +http://www.ietf.org/rfc/rfc1122.txt +http://www.ietf.org/rfc/rfc1123.txt +http://www.ietf.org/rfc/rfc1323.txt +http://www.ietf.org/rfc/rfc1349.txt +http://www.ietf.org/rfc/rfc1521.txt +http://www.ietf.org/rfc/rfc1522.txt +http://www.ietf.org/rfc/rfc1918.txt +http://www.ietf.org/rfc/rfc1950.txt +http://www.ietf.org/rfc/rfc1950.txt.pdf +http://www.ietf.org/rfc/rfc1951.txt +http://www.ietf.org/rfc/rfc1951.txt.pdf +http://www.ietf.org/rfc/rfc1952.txt +http://www.ietf.org/rfc/rfc1952.txt.pdf +http://www.ietf.org/rfc/rfc1964.txt +http://www.ietf.org/rfc/rfc2045.txt +http://www.ietf.org/rfc/rfc2046.txt +http://www.ietf.org/rfc/rfc2078.txt +http://www.ietf.org/rfc/rfc2104.txt +http://www.ietf.org/rfc/rfc2109.txt +http://www.ietf.org/rfc/rfc2222.txt +http://www.ietf.org/rfc/rfc2236.txt +http://www.ietf.org/rfc/rfc2245.txt +http://www.ietf.org/rfc/rfc2246.txt +http://www.ietf.org/rfc/rfc2251.txt +http://www.ietf.org/rfc/rfc2253.txt +http://www.ietf.org/rfc/rfc2254.txt +http://www.ietf.org/rfc/rfc2255.txt +http://www.ietf.org/rfc/rfc2268.txt +http://www.ietf.org/rfc/rfc2278.txt +http://www.ietf.org/rfc/rfc2279.txt +http://www.ietf.org/rfc/rfc2296.txt +http://www.ietf.org/rfc/rfc2365.txt +http://www.ietf.org/rfc/rfc2373.txt +http://www.ietf.org/rfc/rfc2396.txt +http://www.ietf.org/rfc/rfc2440.txt +http://www.ietf.org/rfc/rfc2474.txt +http://www.ietf.org/rfc/rfc2609.txt +http://www.ietf.org/rfc/rfc2616.txt +http://www.ietf.org/rfc/rfc2696 +http://www.ietf.org/rfc/rfc2696.txt +http://www.ietf.org/rfc/rfc2710.txt +http://www.ietf.org/rfc/rfc2732.txt +http://www.ietf.org/rfc/rfc2743.txt +http://www.ietf.org/rfc/rfc2781.txt +http://www.ietf.org/rfc/rfc2782.txt +http://www.ietf.org/rfc/rfc2830.txt +http://www.ietf.org/rfc/rfc2831.txt +http://www.ietf.org/rfc/rfc2853.txt +http://www.ietf.org/rfc/rfc2891.txt +http://www.ietf.org/rfc/rfc2898.txt +http://www.ietf.org/rfc/rfc2965.txt +http://www.ietf.org/rfc/rfc3023.txt +http://www.ietf.org/rfc/rfc3111.txt +http://www.ietf.org/rfc/rfc3275.txt +http://www.ietf.org/rfc/rfc3279.txt +http://www.ietf.org/rfc/rfc3296.txt +http://www.ietf.org/rfc/rfc3330.txt +http://www.ietf.org/rfc/rfc3376.txt +http://www.ietf.org/rfc/rfc3454.txt +http://www.ietf.org/rfc/rfc3490.txt +http://www.ietf.org/rfc/rfc3491.txt +http://www.ietf.org/rfc/rfc3492.txt +http://www.ietf.org/rfc/rfc3530.txt +http://www.ietf.org/rfc/rfc3720.txt +http://www.ietf.org/rfc/rfc3720.txt.pdf +http://www.ietf.org/rfc/rfc3758.txt +http://www.ietf.org/rfc/rfc3810.txt +http://www.ietf.org/rfc/rfc3986.txt +http://www.ietf.org/rfc/rfc4120.txt +http://www.ietf.org/rfc/rfc4122.txt +http://www.ietf.org/rfc/rfc4366.txt +http://www.ietf.org/rfc/rfc4512.txt +http://www.ietf.org/rfc/rfc4648.txt +http://www.ietf.org/rfc/rfc5116.txt +http://www.ietf.org/rfc/rfc5280.txt +http://www.ietf.org/rfc/rfc5890.txt +http://www.ietf.org/rfc/rfc6066.txt +http://www.ietf.org/rfc/rfc7301.txt +http://www.ietf.org/rfc/rfc790.txt +http://www.ietf.org/rfc/rfc793.txt +http://www.ietf.org/rfc/rfc822.txt +http://www.ietf.org/rfc/rfc919.txt +http://www.info-zip.org/doc/appnote-19970311-iz.zip +http://www.ioplex.com/utilities/keytab.txt +http://www.iso.org/iso/home/standards/currency_codes.htm +http://www.jcp.org +http://www.jcp.org/en/jsr/detail?id=203 +http://www.jpeg.org +http://www.libpng.org/pub/png/spec/ +http://www.microsoft.com/typography/otspec/ +http://www.midi.org +http://www.oasis-open.org/committees/entity/spec-2001-08-06.html +http://www.oasis-open.org/committees/tc_home.php?wg_abbrev=dss +http://www.opengroup.org +http://www.oracle.com/technetwork/articles/java/mixing-components-433992.html +http://www.oracle.com/technetwork/java/architecture-142923.html +http://www.oracle.com/technetwork/java/javase/documentation/serialized-criteria-137781.html +http://www.oracle.com/technetwork/java/javase/documentation/spec-136004.html +http://www.oracle.com/technetwork/java/javase/javasecarootcertsprogram-1876540.html +http://www.oracle.com/technetwork/java/javase/tech/javamanagement-140525.html +http://www.oracle.com/technetwork/java/painting-140037.html +http://www.oracle.com/technetwork/java/persistence2-141443.html +http://www.oracle.com/technetwork/java/persistence3-139471.html +http://www.oracle.com/technetwork/java/persistence4-140124.html +http://www.oreilly.com/catalog/regex/ +http://www.oreilly.com/catalog/regex3/ +http://www.reactive-streams.org/ +http://www.relaxng.org/ +http://www.rfc-editor.org/rfc/bcp/bcp47.txt +http://www.saxproject.org +http://www.saxproject.org/ +http://www.unicode.org +http://www.unicode.org/ +http://www.unicode.org/glossary/ +http://www.unicode.org/reports/tr15/ +http://www.unicode.org/reports/tr18/ +http://www.unicode.org/reports/tr24/ +http://www.unicode.org/reports/tr27/ +http://www.unicode.org/reports/tr36/ +http://www.unicode.org/reports/tr44/ +http://www.unicode.org/standard/standard.html +http://www.w3.org/2000/09/xmldsig +http://www.w3.org/2000/xmlns/ +http://www.w3.org/2001/04/xmldsig-more +http://www.w3.org/2001/04/xmlenc +http://www.w3.org/2001/05/xmlschema-errata +http://www.w3.org/2001/10/xml-exc-c14n +http://www.w3.org/2002/06/xmldsig-filter2 +http://www.w3.org/2007/05/xmldsig-more +http://www.w3.org/2009/xmldsig11 +http://www.w3.org/2021/04/xmldsig-more +http://www.w3.org/Graphics/GIF/spec-gif89a.txt +http://www.w3.org/TR/1998/REC-CSS2-19980512 +http://www.w3.org/TR/1999/REC-html401-19991224/ +http://www.w3.org/TR/1999/REC-xml-names-19990114/ +http://www.w3.org/TR/1999/REC-xpath-19991116 +http://www.w3.org/TR/1999/REC-xslt-19991116 +http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510 +http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113 +http://www.w3.org/TR/2000/REC-DOM-Level-2-Events-20001113 +http://www.w3.org/TR/2000/REC-DOM-Level-2-Style-20001113 +http://www.w3.org/TR/2000/REC-DOM-Level-2-Traversal-Range-20001113 +http://www.w3.org/TR/2000/REC-DOM-Level-2-Views-20001113 +http://www.w3.org/TR/2001/REC-xml-c14n-20010315 +http://www.w3.org/TR/2001/REC-xmlschema-1-20010502/ +http://www.w3.org/TR/2003/NOTE-DOM-Level-3-Events-20031107 +http://www.w3.org/TR/2003/REC-DOM-Level-2-HTML-20030109 +http://www.w3.org/TR/2003/REC-SVG11-20030114/ +http://www.w3.org/TR/2003/REC-xptr-framework-20030325/ +http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407 +http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html +http://www.w3.org/TR/2004/REC-DOM-Level-3-LS-20040407 +http://www.w3.org/TR/2004/REC-DOM-Level-3-Val-20040127/ +http://www.w3.org/TR/2004/REC-xml-20040204 +http://www.w3.org/TR/2004/REC-xml-infoset-20040204 +http://www.w3.org/TR/2004/REC-xml-infoset-20040204/ +http://www.w3.org/TR/2004/REC-xml-names11-20040204/ +http://www.w3.org/TR/2004/REC-xml11-20040204/ +http://www.w3.org/TR/DOM-Level-2 +http://www.w3.org/TR/DOM-Level-2-Core/ +http://www.w3.org/TR/DOM-Level-3-Core +http://www.w3.org/TR/DOM-Level-3-LS +http://www.w3.org/TR/ElementTraversal/ +http://www.w3.org/TR/NOTE-datetime +http://www.w3.org/TR/REC-CSS1 +http://www.w3.org/TR/REC-html32.html +http://www.w3.org/TR/REC-xml +http://www.w3.org/TR/REC-xml-names +http://www.w3.org/TR/REC-xml-names/ +http://www.w3.org/TR/REC-xml/ +http://www.w3.org/TR/html4/ +http://www.w3.org/TR/html40/appendix/notes.html +http://www.w3.org/TR/xinclude/ +http://www.w3.org/TR/xml-exc-c14n/ +http://www.w3.org/TR/xml-names11/ +http://www.w3.org/TR/xml-stylesheet/ +http://www.w3.org/TR/xml11/ +http://www.w3.org/TR/xmldsig-core/ +http://www.w3.org/TR/xmldsig-filter2 +http://www.w3.org/TR/xmldsig-filter2/ +http://www.w3.org/TR/xmlschema-1 +http://www.w3.org/TR/xmlschema-1/ +http://www.w3.org/TR/xmlschema-2/ +http://www.w3.org/TR/xpath +http://www.w3.org/TR/xpath-datamodel +http://www.w3.org/TR/xpath/ +http://www.w3.org/TR/xslt +http://www.w3.org/XML/1998/namespace +http://www.w3.org/XML/Schema +http://www.w3.org/XML/xml-V10-2e-errata +http://www.w3.org/pub/WWW/Graphics/Color/sRGB.html +http://www.w3.org/pub/WWW/Protocols/ +http://xmlns.jcp.org/xml/ns//jdbc/webrowset.xsd +https://bugreport.java.com/bugreport/ +https://bugs.openjdk.org/secure/attachment/75649/JVM_CodeHeap_StateAnalytics_V2.pdf +https://cldr.unicode.org/index/downloads +https://csrc.nist.gov/publications/PubsFIPS.html +https://csrc.nist.gov/publications/fips/archive/fips186-2/fips186-2.pdf +https://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf +https://csrc.nist.gov/publications/fips/fips186-3/fips_186-3.pdf +https://csrc.nist.gov/publications/fips/fips197/fips-197.pdf +https://csrc.nist.gov/publications/fips/fips46-3/fips46-3.pdf +https://csrc.nist.gov/publications/fips/fips81/fips81.htm +https://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf +https://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf +https://csrc.nist.gov/pubs/fips/203/final +https://csrc.nist.gov/pubs/fips/204/final +https://datatracker.ietf.org/doc/html/rfc5646 +https://datatracker.ietf.org/doc/html/rfc8017 +https://developer.apple.com/documentation +https://docs.oracle.com/en/java/javase/11/tools/java.html +https://docs.oracle.com/en/java/javase/12/language/index.html +https://docs.oracle.com/en/java/javase/12/tools/java.html +https://docs.oracle.com/en/java/javase/12/vm/compiler-control1.html +https://docs.oracle.com/en/java/javase/13/docs/specs/man/java.html +https://docs.oracle.com/en/java/javase/14/docs/specs/man/java.html +https://docs.oracle.com/en/java/javase/15/docs/specs/man/java.html +https://docs.oracle.com/en/java/javase/16/docs/specs/man/java.html +https://docs.oracle.com/en/java/javase/17/docs/specs/man/java.html +https://docs.oracle.com/en/java/javase/18/docs/specs/man/java.html +https://docs.oracle.com/en/java/javase/19/docs/specs/man/java.html +https://docs.oracle.com/en/java/javase/20/docs/specs/man/java.html +https://docs.oracle.com/en/java/javase/21/docs/specs/man/java.html +https://docs.oracle.com/en/java/javase/22/docs/specs/man/java.html +https://docs.oracle.com/en/java/javase/23/docs/api/java.base/java/lang/Double.html +https://docs.oracle.com/en/java/javase/23/docs/api/java.base/java/math/BigDecimal.html +https://docs.oracle.com/en/java/javase/23/docs/specs/man/java.html +https://docs.oracle.com/en/java/javase/24/docs/specs/man/java.html +https://docs.oracle.com/en/java/javase/@@JAVASE_VERSION@@/docs/api/java.base/java/lang/String.html +https://docs.oracle.com/en/java/javase/@@JAVASE_VERSION@@/docs/specs/javadoc/javadoc-search-spec.html +https://docs.oracle.com/en/java/javase/@@JAVASE_VERSION@@/docs/specs/man/javadoc.html +https://docs.oracle.com/en/java/javase/index.html +https://docs.oracle.com/javase/10/tools/java.htm +https://docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html +https://docs.oracle.com/javase/8/docs/technotes/tools/windows/java.html +https://docs.oracle.com/javase/9/tools/java.htm +https://docs.oracle.com/javase/specs/ +https://docs.oracle.com/javase/specs/jls/se10/html/index.html +https://docs.oracle.com/javase/specs/jls/se11/html/index.html +https://docs.oracle.com/javase/specs/jls/se12/html/index.html +https://docs.oracle.com/javase/specs/jls/se13/html/index.html +https://docs.oracle.com/javase/specs/jls/se14/html/index.html +https://docs.oracle.com/javase/specs/jls/se15/html/index.html +https://docs.oracle.com/javase/specs/jls/se16/html/index.html +https://docs.oracle.com/javase/specs/jls/se17/html/index.html +https://docs.oracle.com/javase/specs/jls/se18/html/index.html +https://docs.oracle.com/javase/specs/jls/se19/html/index.html +https://docs.oracle.com/javase/specs/jls/se20/html/index.html +https://docs.oracle.com/javase/specs/jls/se21/html/index.html +https://docs.oracle.com/javase/specs/jls/se22/html/index.html +https://docs.oracle.com/javase/specs/jls/se22/html/jls-13.html +https://docs.oracle.com/javase/specs/jls/se22/html/jls-14.html +https://docs.oracle.com/javase/specs/jls/se22/html/jls-15.html +https://docs.oracle.com/javase/specs/jls/se22/html/jls-17.html +https://docs.oracle.com/javase/specs/jls/se22/html/jls-3.html +https://docs.oracle.com/javase/specs/jls/se22/html/jls-4.html +https://docs.oracle.com/javase/specs/jls/se22/html/jls-5.html +https://docs.oracle.com/javase/specs/jls/se22/html/jls-6.html +https://docs.oracle.com/javase/specs/jls/se22/html/jls-8.html +https://docs.oracle.com/javase/specs/jls/se22/html/jls-9.html +https://docs.oracle.com/javase/specs/jls/se23/html +https://docs.oracle.com/javase/specs/jls/se23/html/index.html +https://docs.oracle.com/javase/specs/jls/se23/html/jls-10.html +https://docs.oracle.com/javase/specs/jls/se23/html/jls-11.html +https://docs.oracle.com/javase/specs/jls/se23/html/jls-12.html +https://docs.oracle.com/javase/specs/jls/se23/html/jls-14.html +https://docs.oracle.com/javase/specs/jls/se23/html/jls-15.html +https://docs.oracle.com/javase/specs/jls/se23/html/jls-16.html +https://docs.oracle.com/javase/specs/jls/se23/html/jls-18.html +https://docs.oracle.com/javase/specs/jls/se23/html/jls-2.html +https://docs.oracle.com/javase/specs/jls/se23/html/jls-3.html +https://docs.oracle.com/javase/specs/jls/se23/html/jls-4.html +https://docs.oracle.com/javase/specs/jls/se23/html/jls-5.html +https://docs.oracle.com/javase/specs/jls/se23/html/jls-6.html +https://docs.oracle.com/javase/specs/jls/se23/html/jls-7.html +https://docs.oracle.com/javase/specs/jls/se23/html/jls-8.html +https://docs.oracle.com/javase/specs/jls/se23/html/jls-9.html +https://docs.oracle.com/javase/specs/jls/se24/html/index.html +https://docs.oracle.com/javase/specs/jls/se24/html/jls-9.html +https://docs.oracle.com/javase/specs/jls/se@@JAVASE_VERSION@@/html/ +https://docs.oracle.com/javase/specs/jls/se@@JAVASE_VERSION@@/html/index.html +https://docs.oracle.com/javase/specs/jls/se@@JAVASE_VERSION@@/html/jls-10.html +https://docs.oracle.com/javase/specs/jls/se@@JAVASE_VERSION@@/html/jls-11.html +https://docs.oracle.com/javase/specs/jls/se@@JAVASE_VERSION@@/html/jls-12.html +https://docs.oracle.com/javase/specs/jls/se@@JAVASE_VERSION@@/html/jls-13.html +https://docs.oracle.com/javase/specs/jls/se@@JAVASE_VERSION@@/html/jls-14.html +https://docs.oracle.com/javase/specs/jls/se@@JAVASE_VERSION@@/html/jls-15.html +https://docs.oracle.com/javase/specs/jls/se@@JAVASE_VERSION@@/html/jls-17.html +https://docs.oracle.com/javase/specs/jls/se@@JAVASE_VERSION@@/html/jls-18.html +https://docs.oracle.com/javase/specs/jls/se@@JAVASE_VERSION@@/html/jls-3.html +https://docs.oracle.com/javase/specs/jls/se@@JAVASE_VERSION@@/html/jls-4.html +https://docs.oracle.com/javase/specs/jls/se@@JAVASE_VERSION@@/html/jls-5.html +https://docs.oracle.com/javase/specs/jls/se@@JAVASE_VERSION@@/html/jls-6.html +https://docs.oracle.com/javase/specs/jls/se@@JAVASE_VERSION@@/html/jls-7.html +https://docs.oracle.com/javase/specs/jls/se@@JAVASE_VERSION@@/html/jls-8.html +https://docs.oracle.com/javase/specs/jls/se@@JAVASE_VERSION@@/html/jls-9.html +https://docs.oracle.com/javase/specs/jls/se@@JAVASE_VERSION@@/jls@@JAVASE_VERSION@@.pdf +https://docs.oracle.com/javase/specs/jls/se6/html/j3TOC.html +https://docs.oracle.com/javase/specs/jls/se7/html/index.html +https://docs.oracle.com/javase/specs/jls/se8/html/index.html +https://docs.oracle.com/javase/specs/jls/se9/html/index.html +https://docs.oracle.com/javase/specs/jvms/se10/html/index.html +https://docs.oracle.com/javase/specs/jvms/se11/html/index.html +https://docs.oracle.com/javase/specs/jvms/se12/html/index.html +https://docs.oracle.com/javase/specs/jvms/se13/html/index.html +https://docs.oracle.com/javase/specs/jvms/se14/html/index.html +https://docs.oracle.com/javase/specs/jvms/se15/html/index.html +https://docs.oracle.com/javase/specs/jvms/se16/html/index.html +https://docs.oracle.com/javase/specs/jvms/se17/html/index.html +https://docs.oracle.com/javase/specs/jvms/se18/html/index.html +https://docs.oracle.com/javase/specs/jvms/se19/html/index.html +https://docs.oracle.com/javase/specs/jvms/se20/html/index.html +https://docs.oracle.com/javase/specs/jvms/se21/html/index.html +https://docs.oracle.com/javase/specs/jvms/se22/html/index.html +https://docs.oracle.com/javase/specs/jvms/se23/html +https://docs.oracle.com/javase/specs/jvms/se23/html/index.html +https://docs.oracle.com/javase/specs/jvms/se23/html/jvms-5.html +https://docs.oracle.com/javase/specs/jvms/se24/html/index.html +https://docs.oracle.com/javase/specs/jvms/se24/html/jvms-4.html +https://docs.oracle.com/javase/specs/jvms/se@@JAVASE_VERSION@@/html/index.html +https://docs.oracle.com/javase/specs/jvms/se@@JAVASE_VERSION@@/html/jvms-1.html +https://docs.oracle.com/javase/specs/jvms/se@@JAVASE_VERSION@@/html/jvms-2.html +https://docs.oracle.com/javase/specs/jvms/se@@JAVASE_VERSION@@/html/jvms-3.html +https://docs.oracle.com/javase/specs/jvms/se@@JAVASE_VERSION@@/html/jvms-4.html +https://docs.oracle.com/javase/specs/jvms/se@@JAVASE_VERSION@@/html/jvms-5.html +https://docs.oracle.com/javase/specs/jvms/se@@JAVASE_VERSION@@/html/jvms-6.html +https://docs.oracle.com/javase/specs/jvms/se@@JAVASE_VERSION@@/jvms@@JAVASE_VERSION@@.pdf +https://docs.oracle.com/javase/specs/jvms/se7/html/index.html +https://docs.oracle.com/javase/specs/jvms/se8/html/index.html +https://docs.oracle.com/javase/specs/jvms/se9/html/index.html +https://docs.oracle.com/javase/tutorial/ +https://docs.oracle.com/javase/tutorial/2d/text/fonts.html +https://docs.oracle.com/javase/tutorial/extra/fullscreen/index.html +https://docs.oracle.com/javase/tutorial/index.html +https://docs.oracle.com/javase/tutorial/javabeans/ +https://docs.oracle.com/javase/tutorial/javabeans/writing/properties.html +https://docs.oracle.com/javase/tutorial/sound/ +https://docs.oracle.com/javase/tutorial/uiswing/ +https://docs.oracle.com/javase/tutorial/uiswing/components/applet.html +https://docs.oracle.com/javase/tutorial/uiswing/components/border.html +https://docs.oracle.com/javase/tutorial/uiswing/components/button.html +https://docs.oracle.com/javase/tutorial/uiswing/components/colorchooser.html +https://docs.oracle.com/javase/tutorial/uiswing/components/combobox.html +https://docs.oracle.com/javase/tutorial/uiswing/components/dialog.html +https://docs.oracle.com/javase/tutorial/uiswing/components/filechooser.html +https://docs.oracle.com/javase/tutorial/uiswing/components/frame.html +https://docs.oracle.com/javase/tutorial/uiswing/components/generaltext.html +https://docs.oracle.com/javase/tutorial/uiswing/components/icon.html +https://docs.oracle.com/javase/tutorial/uiswing/components/internalframe.html +https://docs.oracle.com/javase/tutorial/uiswing/components/jcomponent.html +https://docs.oracle.com/javase/tutorial/uiswing/components/label.html +https://docs.oracle.com/javase/tutorial/uiswing/components/layeredpane.html +https://docs.oracle.com/javase/tutorial/uiswing/components/list.html +https://docs.oracle.com/javase/tutorial/uiswing/components/menu.html +https://docs.oracle.com/javase/tutorial/uiswing/components/panel.html +https://docs.oracle.com/javase/tutorial/uiswing/components/progress.html +https://docs.oracle.com/javase/tutorial/uiswing/components/rootpane.html +https://docs.oracle.com/javase/tutorial/uiswing/components/scrollpane.html +https://docs.oracle.com/javase/tutorial/uiswing/components/slider.html +https://docs.oracle.com/javase/tutorial/uiswing/components/spinner.html +https://docs.oracle.com/javase/tutorial/uiswing/components/splitpane.html +https://docs.oracle.com/javase/tutorial/uiswing/components/tabbedpane.html +https://docs.oracle.com/javase/tutorial/uiswing/components/table.html +https://docs.oracle.com/javase/tutorial/uiswing/components/text.html +https://docs.oracle.com/javase/tutorial/uiswing/components/textfield.html +https://docs.oracle.com/javase/tutorial/uiswing/components/toolbar.html +https://docs.oracle.com/javase/tutorial/uiswing/components/tooltip.html +https://docs.oracle.com/javase/tutorial/uiswing/components/toplevel.html +https://docs.oracle.com/javase/tutorial/uiswing/components/tree.html +https://docs.oracle.com/javase/tutorial/uiswing/concurrency/index.html +https://docs.oracle.com/javase/tutorial/uiswing/dnd/index.html +https://docs.oracle.com/javase/tutorial/uiswing/events/actionlistener.html +https://docs.oracle.com/javase/tutorial/uiswing/events/componentlistener.html +https://docs.oracle.com/javase/tutorial/uiswing/events/containerlistener.html +https://docs.oracle.com/javase/tutorial/uiswing/events/focuslistener.html +https://docs.oracle.com/javase/tutorial/uiswing/events/index.html +https://docs.oracle.com/javase/tutorial/uiswing/events/internalframelistener.html +https://docs.oracle.com/javase/tutorial/uiswing/events/itemlistener.html +https://docs.oracle.com/javase/tutorial/uiswing/events/keylistener.html +https://docs.oracle.com/javase/tutorial/uiswing/events/mouselistener.html +https://docs.oracle.com/javase/tutorial/uiswing/events/mousemotionlistener.html +https://docs.oracle.com/javase/tutorial/uiswing/events/treeexpansionlistener.html +https://docs.oracle.com/javase/tutorial/uiswing/events/treemodellistener.html +https://docs.oracle.com/javase/tutorial/uiswing/events/treeselectionlistener.html +https://docs.oracle.com/javase/tutorial/uiswing/events/treewillexpandlistener.html +https://docs.oracle.com/javase/tutorial/uiswing/events/windowlistener.html +https://docs.oracle.com/javase/tutorial/uiswing/index.html +https://docs.oracle.com/javase/tutorial/uiswing/layout/box.html +https://docs.oracle.com/javase/tutorial/uiswing/layout/spring.html +https://docs.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html +https://docs.oracle.com/javase/tutorial/uiswing/misc/action.html +https://docs.oracle.com/javase/tutorial/uiswing/misc/focus.html +https://docs.oracle.com/javase/tutorial/uiswing/misc/keybinding.html +https://docs.oracle.com/javase/tutorial/uiswing/misc/timer.html +https://docs.oracle.com/pls/topic/lookup?ctx=javase@@JAVASE_VERSION@@&id=GUID-FE2D2E28-C991-4EF9-9DBE-2A4982726313 +https://docs.oracle.com/pls/topic/lookup?ctx=javase@@JAVASE_VERSION@@&id=homepage +https://docs.oracle.com/pls/topic/lookup?ctx=javase@@JAVASE_VERSION@@&id=i18n_overview +https://docs.oracle.com/pls/topic/lookup?ctx=javase@@JAVASE_VERSION@@&id=imf_overview +https://docs.oracle.com/pls/topic/lookup?ctx=javase@@JAVASE_VERSION@@&id=jndi_ldap_gl_prop +https://docs.oracle.com/pls/topic/lookup?ctx=javase@@JAVASE_VERSION@@&id=jndi_overview +https://docs.oracle.com/pls/topic/lookup?ctx=javase@@JAVASE_VERSION@@&id=logging_overview +https://docs.oracle.com/pls/topic/lookup?ctx=javase@@JAVASE_VERSION@@&id=monitoring_and_management_using_jmx_technology +https://docs.oracle.com/pls/topic/lookup?ctx=javase@@JAVASE_VERSION@@&id=rmi_guide +https://docs.oracle.com/pls/topic/lookup?ctx=javase@@JAVASE_VERSION@@&id=secure_coding_guidelines_javase +https://docs.oracle.com/pls/topic/lookup?ctx=javase@@JAVASE_VERSION@@&id=security_guide_impl_provider +https://docs.oracle.com/pls/topic/lookup?ctx=javase@@JAVASE_VERSION@@&id=security_guide_jca +https://docs.oracle.com/pls/topic/lookup?ctx=javase@@JAVASE_VERSION@@&id=security_guide_jca_provider +https://docs.oracle.com/pls/topic/lookup?ctx=javase@@JAVASE_VERSION@@&id=security_guide_jdk_providers +https://docs.oracle.com/pls/topic/lookup?ctx=javase@@JAVASE_VERSION@@&id=security_guide_jgss_tutorial +https://docs.oracle.com/pls/topic/lookup?ctx=javase@@JAVASE_VERSION@@&id=security_guide_overview +https://docs.oracle.com/pls/topic/lookup?ctx=javase@@JAVASE_VERSION@@&id=security_guide_pki +https://docs.oracle.com/pls/topic/lookup?ctx=javase@@JAVASE_VERSION@@&id=security_guide_sasl +https://docs.oracle.com/pls/topic/lookup?ctx=javase@@JAVASE_VERSION@@&id=security_guide_tools +https://docs.oracle.com/pls/topic/lookup?ctx=javase@@JAVASE_VERSION@@&id=serialization_filter_guide +https://docs.oracle.com/pls/topic/lookup?ctx=javase@@JAVASE_VERSION@@&id=serialver_tool_reference +https://docs.oracle.com/pls/topic/lookup?ctx=javase@@JAVASE_VERSION@@&id=using_jconsole +https://ftp.pwg.org/pub/pwg/candidates/cs-ippoutputbin10-20010207-5100.2.pdf +https://ftp.pwg.org/pub/pwg/standards/temp_archive/pwg5100.3.pdf +https://github.github.com/gfm/ +https://help.ubuntu.com/community/UnityLaunchersAndDesktopFiles +https://html.spec.whatwg.org +https://html.spec.whatwg.org/multipage/ +https://html.spec.whatwg.org/multipage/introduction.html +https://html.spec.whatwg.org/multipage/sections.html +https://html.spec.whatwg.org/multipage/semantics.html +https://jcp.org/aboutJava/communityprocess/maintenance/jsr924/index.html +https://jcp.org/aboutJava/communityprocess/maintenance/jsr924/index2.html +https://jcp.org/aboutJava/communityprocess/mrel/jsr160/index2.html +https://jcp.org/en/jsr/detail?id=14 +https://jcp.org/en/jsr/detail?id=175 +https://jcp.org/en/jsr/detail?id=201 +https://jcp.org/en/jsr/detail?id=221 +https://jcp.org/en/jsr/detail?id=269 +https://jcp.org/en/jsr/detail?id=334 +https://jcp.org/en/jsr/detail?id=335 +https://jcp.org/en/jsr/detail?id=376 +https://jcp.org/en/jsr/detail?id=41 +https://jcp.org/en/procedures/jcp2 +https://mermaid.js.org +https://msdn.microsoft.com/en-us/library/cc236621.aspx +https://msdn.microsoft.com/en-us/library/dd183391.aspx +https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.140-2.pdf +https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf +https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf +https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38F.pdf +https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-90Ar1.pdf +https://openjdk.org/jeps/11 +https://openjdk.org/jeps/12 +https://openjdk.org/jeps/181 +https://openjdk.org/jeps/213 +https://openjdk.org/jeps/225 +https://openjdk.org/jeps/261 +https://openjdk.org/jeps/286 +https://openjdk.org/jeps/306 +https://openjdk.org/jeps/323 +https://openjdk.org/jeps/361 +https://openjdk.org/jeps/371 +https://openjdk.org/jeps/378 +https://openjdk.org/jeps/394 +https://openjdk.org/jeps/395 +https://openjdk.org/jeps/396 +https://openjdk.org/jeps/403 +https://openjdk.org/jeps/409 +https://openjdk.org/jeps/421 +https://openjdk.org/jeps/440 +https://openjdk.org/jeps/441 +https://openjdk.org/jeps/454 +https://openjdk.org/jeps/456 +https://openjdk.org/jeps/458 +https://openjdk.org/jeps/467 +https://openjdk.org/jeps/478 +https://openjdk.org/jeps/487 +https://openjdk.org/jeps/488 +https://openjdk.org/jeps/492 +https://openjdk.org/jeps/494 +https://openjdk.org/jeps/495 +https://openjdk.org/jeps/499 +https://prismjs.com +https://pubs.opengroup.org/onlinepubs/9699919799/functions/inet_addr.html +https://relaxng.org/ +https://reproducible-builds.org/ +https://spec.commonmark.org/0.31.2 +https://spec.commonmark.org/0.31.2/ +https://standards.ieee.org/ieee/754/6210/ +https://standards.iso.org/ittf/PubliclyAvailableStandards/c055982_ISO_IEC_19757-3_2016.zip +https://standards.iso.org/ittf/PubliclyAvailableStandards/index.html +https://support.pkware.com/pkzip/appnote +https://tools.ietf.org/html/rfc1319 +https://tools.ietf.org/html/rfc1321 +https://tools.ietf.org/html/rfc1779 +https://tools.ietf.org/html/rfc2040 +https://tools.ietf.org/html/rfc2104 +https://tools.ietf.org/html/rfc2195 +https://tools.ietf.org/html/rfc2222 +https://tools.ietf.org/html/rfc2246 +https://tools.ietf.org/html/rfc2253 +https://tools.ietf.org/html/rfc2595 +https://tools.ietf.org/html/rfc2616 +https://tools.ietf.org/html/rfc2712 +https://tools.ietf.org/html/rfc2818 +https://tools.ietf.org/html/rfc2830 +https://tools.ietf.org/html/rfc2831 +https://tools.ietf.org/html/rfc3217 +https://tools.ietf.org/html/rfc3278 +https://tools.ietf.org/html/rfc3394 +https://tools.ietf.org/html/rfc3986 +https://tools.ietf.org/html/rfc4086 +https://tools.ietf.org/html/rfc4121 +https://tools.ietf.org/html/rfc4162 +https://tools.ietf.org/html/rfc4178 +https://tools.ietf.org/html/rfc4234 +https://tools.ietf.org/html/rfc4279 +https://tools.ietf.org/html/rfc4346 +https://tools.ietf.org/html/rfc4347 +https://tools.ietf.org/html/rfc4492 +https://tools.ietf.org/html/rfc4512 +https://tools.ietf.org/html/rfc4647 +https://tools.ietf.org/html/rfc4785 +https://tools.ietf.org/html/rfc4960 +https://tools.ietf.org/html/rfc5054 +https://tools.ietf.org/html/rfc5061 +https://tools.ietf.org/html/rfc5084 +https://tools.ietf.org/html/rfc5246 +https://tools.ietf.org/html/rfc5280 +https://tools.ietf.org/html/rfc5288 +https://tools.ietf.org/html/rfc5289 +https://tools.ietf.org/html/rfc5469 +https://tools.ietf.org/html/rfc5487 +https://tools.ietf.org/html/rfc5489 +https://tools.ietf.org/html/rfc5639 +https://tools.ietf.org/html/rfc5646 +https://tools.ietf.org/html/rfc5649 +https://tools.ietf.org/html/rfc5746 +https://tools.ietf.org/html/rfc5932 +https://tools.ietf.org/html/rfc6209 +https://tools.ietf.org/html/rfc6347 +https://tools.ietf.org/html/rfc6367 +https://tools.ietf.org/html/rfc6454 +https://tools.ietf.org/html/rfc6455 +https://tools.ietf.org/html/rfc6655 +https://tools.ietf.org/html/rfc6931 +https://tools.ietf.org/html/rfc7230 +https://tools.ietf.org/html/rfc7231 +https://tools.ietf.org/html/rfc7251 +https://tools.ietf.org/html/rfc7292 +https://tools.ietf.org/html/rfc7507 +https://tools.ietf.org/html/rfc7539 +https://tools.ietf.org/html/rfc7540 +https://tools.ietf.org/html/rfc7748 +https://tools.ietf.org/html/rfc7905 +https://tools.ietf.org/html/rfc7919 +https://tools.ietf.org/html/rfc8017 +https://tools.ietf.org/html/rfc8018 +https://tools.ietf.org/html/rfc8032 +https://tools.ietf.org/html/rfc8103 +https://tools.ietf.org/html/rfc8353 +https://tools.ietf.org/html/rfc8422 +https://tools.ietf.org/html/rfc8446 +https://tools.ietf.org/html/rfc8554 +https://tools.ietf.org/id/draft-kaukonen-cipher-arcfour-03.txt +https://tools.ietf.org/rfc/rfc5280.txt +https://tools.ietf.org/rfc/rfc8017.txt +https://unicode.org/reports/tr31/ +https://unicode.org/reports/tr35/ +https://unicode.org/reports/tr35/tr35-dates.html +https://unicode.org/reports/tr35/tr35-numbers.html +https://unicode.org/reports/tr51/ +https://web.mit.edu/kerberos/ +https://webhome.phy.duke.edu/~rgb/General/dieharder.php +https://www.cipa.jp/std/documents/e/DC-008-2012_E.pdf +https://www.color.org +https://www.color.org/ICC1V42.pdf +https://www.iana.org/assignments/kerberos-parameters/kerberos-parameters.xhtml +https://www.iana.org/assignments/language-subtag-registry/language-subtag-registry +https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml +https://www.iana.org/time-zones +https://www.ietf.org/rfc/rfc2616.txt +https://www.ietf.org/rfc/rfc2818.txt +https://www.ietf.org/rfc/rfc6931.txt +https://www.ietf.org/rfc/rfc6943.html +https://www.iso.org/home.html +https://www.iso.org/iso-4217-currency-codes.html +https://www.iso.org/iso-8601-date-and-time-format.html +https://www.iso.org/standard/18114.html +https://www.itu.int/itudoc/itu-t/com16/tiff-fx/docs/tiff6.pdf +https://www.itu.int/rec/T-REC-X.509/en +https://www.netlib.org/fdlibm/ +https://www.oasis-open.org +https://www.oasis-open.org/committees/download.php/14809/xml-catalogs.html +https://www.oracle.com/java/javase/terms/license/java@@JAVASE_VERSION@@speclicense.html +https://www.oracle.com/java/technologies/a-swing-architecture.html +https://www.oracle.com/java/technologies/javase/seccodeguide.html +https://www.oracle.com/java/technologies/javase/training-support.html +https://www.oracle.com/pls/topic/lookup?ctx=en/java/javase&id=security_guide_implement_provider_jca +https://www.oracle.com/technetwork/java/javase/documentation/spec-136004.html +https://www.oracle.com/technetwork/java/javasebusiness/downloads/java-archive-downloads-java-plat-419418.html +https://www.oracle.com/technetwork/java/redist-137594.html +https://www.oracle.com/technetwork/java/seccodeguide-139067.html +https://www.owasp.org +https://www.rfc-editor.org/info/rfc1122 +https://www.rfc-editor.org/info/rfc1123 +https://www.rfc-editor.org/info/rfc1323 +https://www.rfc-editor.org/info/rfc1349 +https://www.rfc-editor.org/info/rfc1738 +https://www.rfc-editor.org/info/rfc1779 +https://www.rfc-editor.org/info/rfc1918 +https://www.rfc-editor.org/info/rfc1950 +https://www.rfc-editor.org/info/rfc1951 +https://www.rfc-editor.org/info/rfc1952 +https://www.rfc-editor.org/info/rfc2040 +https://www.rfc-editor.org/info/rfc2045 +https://www.rfc-editor.org/info/rfc2046 +https://www.rfc-editor.org/info/rfc2109 +https://www.rfc-editor.org/info/rfc2236 +https://www.rfc-editor.org/info/rfc2246 +https://www.rfc-editor.org/info/rfc2253 +https://www.rfc-editor.org/info/rfc2268 +https://www.rfc-editor.org/info/rfc2278 +https://www.rfc-editor.org/info/rfc2279 +https://www.rfc-editor.org/info/rfc2296 +https://www.rfc-editor.org/info/rfc2306 +https://www.rfc-editor.org/info/rfc2365 +https://www.rfc-editor.org/info/rfc2368 +https://www.rfc-editor.org/info/rfc2373 +https://www.rfc-editor.org/info/rfc2396 +https://www.rfc-editor.org/info/rfc2474 +https://www.rfc-editor.org/info/rfc2560 +https://www.rfc-editor.org/info/rfc2616 +https://www.rfc-editor.org/info/rfc2710 +https://www.rfc-editor.org/info/rfc2732 +https://www.rfc-editor.org/info/rfc2781 +https://www.rfc-editor.org/info/rfc2898 +https://www.rfc-editor.org/info/rfc2911 +https://www.rfc-editor.org/info/rfc2965 +https://www.rfc-editor.org/info/rfc3279 +https://www.rfc-editor.org/info/rfc3330 +https://www.rfc-editor.org/info/rfc3376 +https://www.rfc-editor.org/info/rfc3454 +https://www.rfc-editor.org/info/rfc3490 +https://www.rfc-editor.org/info/rfc3491 +https://www.rfc-editor.org/info/rfc3492 +https://www.rfc-editor.org/info/rfc3530 +https://www.rfc-editor.org/info/rfc3720 +https://www.rfc-editor.org/info/rfc3810 +https://www.rfc-editor.org/info/rfc3986 +https://www.rfc-editor.org/info/rfc4007 +https://www.rfc-editor.org/info/rfc4086 +https://www.rfc-editor.org/info/rfc4122 +https://www.rfc-editor.org/info/rfc4234 +https://www.rfc-editor.org/info/rfc4366 +https://www.rfc-editor.org/info/rfc4512 +https://www.rfc-editor.org/info/rfc4647 +https://www.rfc-editor.org/info/rfc4648 +https://www.rfc-editor.org/info/rfc5116 +https://www.rfc-editor.org/info/rfc5280 +https://www.rfc-editor.org/info/rfc5646 +https://www.rfc-editor.org/info/rfc5869 +https://www.rfc-editor.org/info/rfc5890 +https://www.rfc-editor.org/info/rfc6066 +https://www.rfc-editor.org/info/rfc7301 +https://www.rfc-editor.org/info/rfc7539 +https://www.rfc-editor.org/info/rfc790 +https://www.rfc-editor.org/info/rfc793 +https://www.rfc-editor.org/info/rfc8017 +https://www.rfc-editor.org/info/rfc8032 +https://www.rfc-editor.org/info/rfc822 +https://www.rfc-editor.org/info/rfc919 +https://www.rfc-editor.org/info/rfc9231 +https://www.rfc-editor.org/rfc/rfc2315.txt +https://www.rfc-editor.org/rfc/rfc5208.html +https://www.rfc-editor.org/rfc/rfc5280.html +https://www.rfc-editor.org/rfc/rfc5646 +https://www.rfc-editor.org/rfc/rfc5646.html +https://www.rfc-editor.org/rfc/rfc5869 +https://www.rfc-editor.org/rfc/rfc6943.html +https://www.rfc-editor.org/rfc/rfc8017 +https://www.rfc-editor.org/rfc/rfc8017.html +https://www.rfc-editor.org/rfc/rfc9180 +https://www.schneier.com/blowfish.html +https://www.secg.org/sec2-v2.pdf +https://www.unicode.org/reports/tr15 +https://www.unicode.org/reports/tr15/ +https://www.unicode.org/reports/tr18 +https://www.unicode.org/reports/tr24 +https://www.unicode.org/reports/tr27 +https://www.unicode.org/reports/tr29/ +https://www.unicode.org/reports/tr31 +https://www.unicode.org/reports/tr35 +https://www.unicode.org/reports/tr35/ +https://www.unicode.org/reports/tr35/tr35-collation.html +https://www.unicode.org/reports/tr35/tr35-dates.html +https://www.unicode.org/reports/tr35/tr35-general.html +https://www.unicode.org/reports/tr35/tr35.html +https://www.unicode.org/reports/tr36 +https://www.unicode.org/reports/tr44 +https://www.unicode.org/reports/tr44/ +https://www.usno.navy.mil/USNO +https://www.usno.navy.mil/USNO/time/master-clock/systems-of-time +https://www.w3.org +https://www.w3.org/Daemon/User/Config/Logging.html +https://www.w3.org/TR/1998/REC-html40-19980424/ +https://www.w3.org/TR/1999/REC-xpath-19991116/ +https://www.w3.org/TR/2001/REC-xml-c14n-20010315 +https://www.w3.org/TR/2002/REC-xml-exc-c14n-20020718/ +https://www.w3.org/TR/2002/REC-xmldsig-filter2-20021108/ +https://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html +https://www.w3.org/TR/CSS22 +https://www.w3.org/TR/CSS22/syndata.html +https://www.w3.org/TR/DOM-Level-3-XPath/ +https://www.w3.org/TR/NOTE-datetime +https://www.w3.org/TR/REC-CSS1 +https://www.w3.org/TR/REC-html32.html +https://www.w3.org/TR/REC-xml-names/ +https://www.w3.org/TR/html4 +https://www.w3.org/TR/html52 +https://www.w3.org/TR/html52/dom.html +https://www.w3.org/TR/html52/syntax.html +https://www.w3.org/TR/xml +https://www.w3.org/TR/xml-c14n11/ +https://www.w3.org/TR/xml/ +https://www.w3.org/TR/xmldsig-core/ +https://www.w3.org/TR/xmlschema-2 +https://www.w3.org/WAI/standards-guidelines/wcag/ +https://www.w3.org/XML/Schema +https://www.w3.org/XML/xml-names-19990114-errata.html +https://www.wapforum.org/what/technical/SPEC-WAESpec-19990524.pdf diff --git a/test/docs/jdk/javadoc/doccheck/checks/jdkCheckExtlinks.java b/test/docs/jdk/javadoc/doccheck/checks/jdkCheckExtlinks.java new file mode 100644 index 00000000000..846cf917c3a --- /dev/null +++ b/test/docs/jdk/javadoc/doccheck/checks/jdkCheckExtlinks.java @@ -0,0 +1,31 @@ +/* + * 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 8337109 + * @summary Check external links in the generated documentation + * @library /test/langtools/tools/lib ../../doccheck /test/lib ../../../../tools/tester + * @build DocTester toolbox.TestRunner + * @run main/othervm -Ddoccheck.checks=extlinks DocCheck + */ diff --git a/test/docs/jdk/javadoc/doccheck/checks/jdkCheckHtml.java b/test/docs/jdk/javadoc/doccheck/checks/jdkCheckHtml.java new file mode 100644 index 00000000000..3e9f3ab9f82 --- /dev/null +++ b/test/docs/jdk/javadoc/doccheck/checks/jdkCheckHtml.java @@ -0,0 +1,31 @@ +/* + * 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 8337109 + * @summary Check the html in the generated documentation + * @library /test/langtools/tools/lib ../../doccheck /test/lib ../../../../tools/tester + * @build DocTester toolbox.TestRunner + * @run main/othervm -Ddoccheck.checks=html DocCheck + */ diff --git a/test/docs/jdk/javadoc/doccheck/checks/jdkCheckLinks.java b/test/docs/jdk/javadoc/doccheck/checks/jdkCheckLinks.java new file mode 100644 index 00000000000..bd818923d9f --- /dev/null +++ b/test/docs/jdk/javadoc/doccheck/checks/jdkCheckLinks.java @@ -0,0 +1,31 @@ +/* + * 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 8337109 + * @summary Check Links in the generated documentation + * @library /test/langtools/tools/lib ../../doccheck /test/lib ../../../../tools/tester + * @build DocTester toolbox.TestRunner + * @run main/othervm -Ddoccheck.checks=links DocCheck + */ diff --git a/test/docs/jdk/javadoc/TestDocs.java b/test/docs/jdk/javadoc/doccheck/checks/jdkDoctypeBadcharsCheck.java similarity index 63% rename from test/docs/jdk/javadoc/TestDocs.java rename to test/docs/jdk/javadoc/doccheck/checks/jdkDoctypeBadcharsCheck.java index 3ccd89ab2e0..a0c145e2b79 100644 --- a/test/docs/jdk/javadoc/TestDocs.java +++ b/test/docs/jdk/javadoc/doccheck/checks/jdkDoctypeBadcharsCheck.java @@ -23,22 +23,9 @@ /* * @test - * @library /test/lib ../../tools/tester - * @build jtreg.SkippedException - * @summary example of a test on the generated documentation - * @run main TestDocs + * @bug 8337109 + * @summary Check doctype and character encoding in the generated documentation + * @library /test/langtools/tools/lib ../../doccheck /test/lib ../../../../tools/tester + * @build DocTester toolbox.TestRunner + * @run main/othervm -Ddoccheck.checks=doctype,badchars DocCheck */ - -import java.nio.file.Files; - -public class TestDocs { - public static void main(String... args) throws Exception { - var docs = DocTester.resolveDocs(); - System.err.println("Path to the docs is: " + docs); - System.err.println("Do docs exits?"); - System.err.println(Files.exists(docs)); - System.err.println("tidy location"); - System.err.println(System.getProperty("tidy")); - System.err.println("End of test"); - } -} diff --git a/test/docs/jdk/javadoc/doccheck/doccheckutils/Checker.java b/test/docs/jdk/javadoc/doccheck/doccheckutils/Checker.java new file mode 100644 index 00000000000..614c32105a6 --- /dev/null +++ b/test/docs/jdk/javadoc/doccheck/doccheckutils/Checker.java @@ -0,0 +1,39 @@ +/* + * 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 doccheckutils; + +import java.io.Closeable; + +/** + * Base class for {@link FileChecker file checkers} and + */ +public interface Checker extends Closeable { + + /** + * Writes a report at the end of a run, to summarize the results of the + * checking done by this checker. + */ + void report(); + + boolean isOK(); +} diff --git a/test/docs/jdk/javadoc/doccheck/doccheckutils/FileChecker.java b/test/docs/jdk/javadoc/doccheck/doccheckutils/FileChecker.java new file mode 100644 index 00000000000..4577c3b2b26 --- /dev/null +++ b/test/docs/jdk/javadoc/doccheck/doccheckutils/FileChecker.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. + */ +package doccheckutils; + +import java.nio.file.Path; +import java.util.List; + +public interface FileChecker extends Checker { + void checkFiles(List files); +} diff --git a/test/docs/jdk/javadoc/doccheck/doccheckutils/FileProcessor.java b/test/docs/jdk/javadoc/doccheck/doccheckutils/FileProcessor.java new file mode 100644 index 00000000000..6ae3a473bdb --- /dev/null +++ b/test/docs/jdk/javadoc/doccheck/doccheckutils/FileProcessor.java @@ -0,0 +1,64 @@ +/* + * 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 doccheckutils; + +import java.io.IOException; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.ArrayList; +import java.util.List; + +public class FileProcessor { + private final List files; + + public FileProcessor() { + files = new ArrayList<>(); + } + + public List getFiles() { + return files; + } + + public void processFiles(Path directory) { + try { + Files.walkFileTree(directory, new SimpleFileVisitor() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + if (file.toString().endsWith(".html")) + files.add(file); + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { + return FileVisitResult.CONTINUE; + } + }); + } catch (IOException e) { + throw new RuntimeException(); + } + } +} diff --git a/test/docs/jdk/javadoc/doccheck/doccheckutils/HtmlChecker.java b/test/docs/jdk/javadoc/doccheck/doccheckutils/HtmlChecker.java new file mode 100644 index 00000000000..e27c21ea212 --- /dev/null +++ b/test/docs/jdk/javadoc/doccheck/doccheckutils/HtmlChecker.java @@ -0,0 +1,94 @@ +/* + * 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 doccheckutils; + +import java.nio.file.Path; +import java.util.Map; + +/** + * Base class for HTML checkers. + *

+ * For details on HTML syntax and the terms used in this API, see + * W3C The HTML syntax. + */ +public interface HtmlChecker extends Checker { + /** + * Starts checking a new file, + *

+ * The file becomes the current file until {@link #endFile endFile} + * is called. + * + * @param path the file. + */ + void startFile(Path path); + + /** + * Ends checking the current file. + */ + void endFile(); + + /** + * Checks the content of a {@code } declaration in the + * current file. + * + * @param line the line number on which the declaration was found + * @param attrs the content of the declaration + */ + void xml(int line, Map attrs); + + /** + * Checks the content of a {@code } declaration in the + * current file. + * + * @param line the line number on which the declaration was found + * @param docType the content of the declaration + */ + void docType(int line, String docType); + + /** + * Checks the start of an HTML tag in the current file. + * + * @param line the line number on which the start tag for an element was found + * @param name the name of the tag + * @param attrs the attributes of the tag + * @param selfClosing whether the tag is self-closing + */ + void startElement(int line, String name, Map attrs, boolean selfClosing); + + /** + * Checks the end of an HTML tag in the current file. + * + * @param line the line number on which the end tag for an element was found + * @param name the name of the tag + */ + void endElement(int line, String name); + + /** + * Checks the content appearing in between HTML tags. + * + * @param line the line number on which the content was found + * @param content the content + */ + default void content(int line, String content) { + } +} diff --git a/test/docs/jdk/javadoc/doccheck/doccheckutils/HtmlFileChecker.java b/test/docs/jdk/javadoc/doccheck/doccheckutils/HtmlFileChecker.java new file mode 100644 index 00000000000..e9ba1643c50 --- /dev/null +++ b/test/docs/jdk/javadoc/doccheck/doccheckutils/HtmlFileChecker.java @@ -0,0 +1,389 @@ +/* + * 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 doccheckutils; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.charset.CharsetDecoder; +import java.nio.charset.CodingErrorAction; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.regex.Pattern; + +/** + * Reads an HTML file, and calls a series of{@link HtmlChecker HTML checkers} + * for the HTML constructs found therein. + */ +public class HtmlFileChecker implements FileChecker { + private final CharsetDecoder decoder = StandardCharsets.UTF_8.newDecoder() + .onMalformedInput(CodingErrorAction.IGNORE) + .onUnmappableCharacter(CodingErrorAction.IGNORE); + + private final Log log; + private final HtmlChecker htmlChecker; + private Path path; + private BufferedReader in; + private int ch; + private int lineNumber; + private boolean inScript; + private boolean xml; + + public HtmlFileChecker(HtmlChecker htmlChecker, Path BaseDir) { + this.log = new Log(); + log.setBaseDirectory(BaseDir); + this.htmlChecker = htmlChecker; + } + + @Override + public void checkFiles(List files) { + for (Path file : files) { + read(file); + } + } + + @Override + public void report() { + System.err.println(log); + } + + @Override + public void close() throws IOException { +// report(); + htmlChecker.close(); + } + + private void read(Path path) { + try (BufferedReader r = new BufferedReader( + new InputStreamReader(Files.newInputStream(path), decoder))) { + this.path = path; + this.in = r; + StringBuilder content = new StringBuilder(); + + startFile(path); + try { + lineNumber = 1; + xml = false; + nextChar(); + + while (ch != -1) { + if (ch == '<') { + content(content.toString()); + content.setLength(0); + html(); + } else { + content.append((char) ch); + if (ch == '\n') { + content(content.toString()); + content.setLength(0); + } + nextChar(); + } + } + } finally { + endFile(); + } + } catch (IOException e) { + log.log(path, lineNumber, e); + } catch (Throwable t) { + log.log(path, lineNumber, t); + log.log(String.valueOf(t)); + } + } + + private void startFile(Path path) { + htmlChecker.startFile(path); + } + + private void endFile() { + htmlChecker.endFile(); + } + + private void docType(String s) { + htmlChecker.docType(lineNumber, s); + } + + private void startElement(String name, Map attrs, boolean selfClosing) { + htmlChecker.startElement(lineNumber, name, attrs, selfClosing); + } + + private void endElement(String name) { + htmlChecker.endElement(lineNumber, name); + } + + private void content(String s) { + htmlChecker.content(lineNumber, s); + } + + private void nextChar() throws IOException { + ch = in.read(); + if (ch == '\n') + lineNumber++; + } + + /** + * Read the start or end of an HTML tag, or an HTML comment + * {@literal } or {@literal } + * + * @throws IOException if there is a problem reading the file + */ + protected void html() throws IOException { + nextChar(); + if (isIdentifierStart((char) ch)) { + String name = readIdentifier().toLowerCase(Locale.US); + Map attrs = htmlAttrs(); + if (attrs != null) { + boolean selfClosing = false; + if (ch == '/') { + nextChar(); + selfClosing = true; + } + if (ch == '>') { + nextChar(); + startElement(name, attrs, selfClosing); + if (name.equals("script")) { + inScript = true; + } + return; + } + } + } else if (ch == '/') { + nextChar(); + if (isIdentifierStart((char) ch)) { + String name = readIdentifier().toLowerCase(Locale.US); + skipWhitespace(); + if (ch == '>') { + nextChar(); + endElement(name); + if (name.equals("script")) { + inScript = false; + } + return; + } + } + } else if (ch == '!') { + nextChar(); + if (ch == '-') { + nextChar(); + if (ch == '-') { + nextChar(); + while (ch != -1) { + int dash = 0; + while (ch == '-') { + dash++; + nextChar(); + } + // Strictly speaking, a comment should not contain "--" + // so dash > 2 is an error, dash == 2 implies ch == '>' + // See http://www.w3.org/TR/html-markup/syntax.html#syntax-comments + // for more details. + if (dash >= 2 && ch == '>') { + nextChar(); + return; + } + + nextChar(); + } + } + } else if (ch == '[') { + nextChar(); + if (ch == 'C') { + nextChar(); + if (ch == 'D') { + nextChar(); + if (ch == 'A') { + nextChar(); + if (ch == 'T') { + nextChar(); + if (ch == 'A') { + nextChar(); + if (ch == '[') { + while (true) { + nextChar(); + if (ch == ']') { + nextChar(); + if (ch == ']') { + nextChar(); + if (ch == '>') { + nextChar(); + return; + } + } + } + } + + } + } + } + } + } + } + } else { + StringBuilder sb = new StringBuilder(); + while (ch != -1 && ch != '>') { + sb.append((char) ch); + nextChar(); + } + Pattern p = Pattern.compile("(?is)doctype\\s+html\\s?.*"); + String s = sb.toString(); + if (p.matcher(s).matches()) { + xml = s.contains("XHTML"); + docType(s); + return; + } + } + } else if (ch == '?') { + nextChar(); + if (ch == 'x') { + nextChar(); + if (ch == 'm') { + nextChar(); + if (ch == 'l') { + nextChar(); + if (ch == '?') { + nextChar(); + if (ch == '>') { + nextChar(); + xml = true; + return; + } + } + } + } + + } + } + + if (!inScript) { + log.log(path, lineNumber, "bad html"); + } + } + + /** + * Read a series of HTML attributes, terminated by {@literal > }. + * Each attribute is of the form {@literal identifier[=value] }. + * "value" may be unquoted, single-quoted, or double-quoted. + */ + protected Map htmlAttrs() throws IOException { + Map map = new LinkedHashMap<>(); + skipWhitespace(); + + while (isIdentifierStart((char) ch)) { + String name = readAttributeName().toLowerCase(Locale.US); + skipWhitespace(); + String value = null; + if (ch == '=') { + nextChar(); + skipWhitespace(); + if (ch == '\'' || ch == '"') { + char quote = (char) ch; + nextChar(); + StringBuilder sb = new StringBuilder(); + while (ch != -1 && ch != quote) { +// if (ch == '\n') { +// error(path, lineNumber, "unterminated string"); +// // No point trying to read more. +// // In fact, all attrs get discarded by the caller +// // and superseded by a malformed.html node because +// // the html tag itself is not terminated correctly. +// break loop; +// } + sb.append((char) ch); + nextChar(); + } + value = sb.toString() // hack to replace common entities + .replace("<", "<") + .replace(">", ">") + .replace("&", "&"); + nextChar(); + } else { + StringBuilder sb = new StringBuilder(); + while (ch != -1 && !isUnquotedAttrValueTerminator((char) ch)) { + sb.append((char) ch); + nextChar(); + } + value = sb.toString(); + } + skipWhitespace(); + } + map.put(name, value); + } + + return map; + } + + protected boolean isIdentifierStart(char ch) { + return Character.isUnicodeIdentifierStart(ch); + } + + protected String readIdentifier() throws IOException { + StringBuilder sb = new StringBuilder(); + sb.append((char) ch); + nextChar(); + while (ch != -1 && Character.isUnicodeIdentifierPart(ch)) { + sb.append((char) ch); + nextChar(); + } + return sb.toString(); + } + + protected String readAttributeName() throws IOException { + StringBuilder sb = new StringBuilder(); + sb.append((char) ch); + nextChar(); + while ((ch != -1 && Character.isUnicodeIdentifierPart(ch)) + || ch == '-' + || (xml && ch == ':')) { + sb.append((char) ch); + nextChar(); + } + return sb.toString(); + } + + protected boolean isWhitespace(char ch) { + return Character.isWhitespace(ch); + } + + protected void skipWhitespace() throws IOException { + while (isWhitespace((char) ch)) { + nextChar(); + } + } + + protected boolean isUnquotedAttrValueTerminator(char ch) { + return switch (ch) { + case '\f', '\n', '\r', '\t', ' ', '"', '\'', '`', '=', '<', '>' -> true; + default -> false; + }; + } + + @Override + public boolean isOK() { + throw new UnsupportedOperationException(); + } +} diff --git a/test/docs/jdk/javadoc/doccheck/doccheckutils/Log.java b/test/docs/jdk/javadoc/doccheck/doccheckutils/Log.java new file mode 100644 index 00000000000..9626c59e9ca --- /dev/null +++ b/test/docs/jdk/javadoc/doccheck/doccheckutils/Log.java @@ -0,0 +1,95 @@ +/* + * 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 doccheckutils; + +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; + +public class Log { + private final ArrayList errors; + + private Path baseDir; + + public Log() { + errors = new ArrayList<>(); + } + + public List getErrors() { + return errors; + } + + public void log(Path path, int line, String message, Object... args) { + errors.add(formatErrorMessage(path, line, message, args)); + } + + + public String formatErrorMessage(Path path, int line, String message, Object... args) { + return path + ":" + line + ": " + formatErrorMessage(message, args); + } + + public String formatErrorMessage(Path path, int line, Throwable t) { + return path + ":" + line + ": " + t; + } + + public String formatErrorMessage(Path path, Throwable t) { + return path + ": " + t; + } + + + public String formatErrorMessage(String message, Object... args) { + return String.format(message, args); + } + + public void log(String message) { + errors.add(message); + } + + public void log(Path path, int lineNumber, String s, int errorsOnLine) { + log(formatErrorMessage(path, lineNumber, s, errorsOnLine)); + } + + public void log(Path path, int line, Throwable t) { + log(formatErrorMessage(path, line, t)); + } + + public void log(Path path, Throwable t) { + log(formatErrorMessage(path, t)); + } + + public void log(String message, Object... args) { + log(formatErrorMessage(message, args)); + } + + public void setBaseDirectory(Path baseDir) { + this.baseDir = baseDir.toAbsolutePath(); + } + + public Path relativize(Path path) { + return baseDir != null && path.startsWith(baseDir) ? baseDir.relativize(path) : path; + } + + public boolean noErrors() { + return errors.isEmpty(); + } +} diff --git a/test/docs/jdk/javadoc/doccheck/doccheckutils/checkers/BadCharacterChecker.java b/test/docs/jdk/javadoc/doccheck/doccheckutils/checkers/BadCharacterChecker.java new file mode 100644 index 00000000000..f979c34c9a3 --- /dev/null +++ b/test/docs/jdk/javadoc/doccheck/doccheckutils/checkers/BadCharacterChecker.java @@ -0,0 +1,158 @@ +/* + * 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 doccheckutils.checkers; + +import doccheckutils.FileChecker; +import doccheckutils.Log; + +import java.io.*; +import java.nio.charset.Charset; +import java.nio.charset.CharsetDecoder; +import java.nio.charset.CodingErrorAction; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.text.MessageFormat; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Checks the contents of an HTML file for bad/unmappable characters. + *

+ * The file encoding is determined from the file contents. + */ +public class BadCharacterChecker implements FileChecker, AutoCloseable { + private static final Pattern doctype = Pattern.compile("(?i)"); + private static final Pattern metaCharset = Pattern.compile("(?i)"); + private static final Pattern metaContentType = Pattern.compile("(?i)"); + private final Log errors; + private int files = 0; + private int badFiles = 0; + + public BadCharacterChecker() { + errors = new Log(); + } + + public void checkFile(Path path) { + files++; + boolean ok = true; + try (InputStream in = new BufferedInputStream(Files.newInputStream(path))) { + CharsetDecoder d = getCharset(in).newDecoder() + .onMalformedInput(CodingErrorAction.REPLACE) + .onUnmappableCharacter(CodingErrorAction.REPLACE); + BufferedReader r = new BufferedReader(new InputStreamReader(in, d)); + int lineNumber = 0; + String line; + try { + while ((line = r.readLine()) != null) { + lineNumber++; + int errorsOnLine = 0; + for (int i = 0; i < line.length(); i++) { + char ch = line.charAt(i); + if (ch == 0xFFFD) { + errorsOnLine++; + } + } + if (errorsOnLine > 0) { + errors.log(path, lineNumber, "found %d invalid characters", errorsOnLine); + ok = false; + } + } + } catch (IOException e) { + errors.log(path, lineNumber, e); + ok = false; + + } + } catch (IOException e) { + errors.log(path, e); + ok = false; + } + if (!ok) + badFiles++; + } + + @Override + public void checkFiles(List files) { + for (Path file : files) { + checkFile(file); + } + } + + private Charset getCharset(InputStream in) throws IOException { + CharsetDecoder initial = StandardCharsets.US_ASCII.newDecoder() + .onMalformedInput(CodingErrorAction.REPLACE) + .onUnmappableCharacter(CodingErrorAction.REPLACE); + + in.mark(1024); + try { + BufferedReader r = new BufferedReader(new InputStreamReader(in, initial)); + char[] buf = new char[1024]; + int n = r.read(buf, 0, buf.length); + String head = new String(buf, 0, n); + boolean html5 = doctype.matcher(head).find(); + Matcher m1 = metaCharset.matcher(head); + if (m1.find()) { + return Charset.forName(m1.group(1)); + } + Matcher m2 = metaContentType.matcher(head); + if (m2.find()) { + return Charset.forName(m2.group(1)); + } + return html5 ? StandardCharsets.UTF_8 : StandardCharsets.ISO_8859_1; + } finally { + in.reset(); + } + } + + @Override + public void report() { + if (!errors.noErrors() && files > 0) { + System.err.println("Bad characters found in the generated HTML"); + + System.err.println(MessageFormat.format( + """ + Bad Characters Report + {0} files read + {1} files contained bad characters" + {2} bad characters or other errors found + """, + files, badFiles, files)); + + for (String s : errors.getErrors()) { + System.err.println(s); + } + throw new RuntimeException("Bad character found in the generated HTML"); + } + } + + @Override + public boolean isOK() { + return errors.noErrors(); + } + + @Override + public void close() { + report(); + } +} diff --git a/test/docs/jdk/javadoc/doccheck/doccheckutils/checkers/DocTypeChecker.java b/test/docs/jdk/javadoc/doccheck/doccheckutils/checkers/DocTypeChecker.java new file mode 100644 index 00000000000..1f53318de18 --- /dev/null +++ b/test/docs/jdk/javadoc/doccheck/doccheckutils/checkers/DocTypeChecker.java @@ -0,0 +1,159 @@ +/* + * 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 doccheckutils.checkers; + +import doccheckutils.HtmlChecker; +import doccheckutils.Log; + +import java.io.IOException; +import java.nio.file.Path; +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Checks the DocType declared at the head of an HTML file. + * + * @see + * W3C HTML5 8.1.1 The DOCTYPE + */ +public class DocTypeChecker implements HtmlChecker { + private final Log log; + private final Map counts = new HashMap<>(); + private int html5; + private int html5_legacy; + private int xml; + private int other; + + private Path path; + + public DocTypeChecker() { + log = new Log(); + } + + @Override + public void startFile(Path path) { + this.path = path; + } + + @Override + public void endFile() { + } + + @Override + public void xml(int line, Map attrs) { + xml++; + } + + @Override + public void docType(int line, String docType) { + if (docType.equalsIgnoreCase("doctype html")) { + html5++; + } else { + Pattern p = Pattern.compile("(?i)doctype" + + "\\s+html" + + "\\s+([a-z]+)" + + "\\s+(?:\"([^\"]+)\"|'([^']+)')" + + "(?:\\s+(?:\"([^\"]+)\"|'([^']+)'))?" + + "\\s*"); + Matcher m = p.matcher(docType); + if (m.matches()) { + // See http://www.w3.org/tr/html52/syntax.html#the-doctype + if (m.group(1).equalsIgnoreCase("system") + && m.group(2).equals("about:legacy-compat")) { + html5_legacy++; + } else { + String version = m.group(2); + List allowedVersions = List.of( + "-//W3C//DTD XHTML 1.0 Strict//EN" + ); + if (allowedVersions.stream().noneMatch(v -> v.equals(version))) { + log.log(path, line, "unexpected doctype: " + version); + } + counts.put(version, counts.getOrDefault(version, 0) + 1); + } + } else { + log.log(path, line, "doctype not recognized: " + docType); + other++; + } + } + } + + @Override + public void startElement(int line, String name, Map attrs, boolean selfClosing) { + } + + @Override + public void endElement(int line, String name) { + } + + @Override + public void report() { + log.log("DocType Report"); + if (xml > 0) { + log.log("%6d: XHTML%n", xml); + } + if (html5 > 0) { + log.log("%6d: HTML5%n", html5); + } + if (html5_legacy > 0) { + log.log("%6d: HTML5 (legacy)%n", html5_legacy); + } + + Map> sortedCounts = new TreeMap<>(Comparator.reverseOrder()); + + for (Map.Entry e : counts.entrySet()) { + String s = e.getKey(); + Integer n = e.getValue(); + Set set = sortedCounts.computeIfAbsent(n, k -> new TreeSet<>()); + set.add(s); + } + + for (Map.Entry> e : sortedCounts.entrySet()) { + for (String p : e.getValue()) { + log.log("%6d: %s%n", e.getKey(), p); + } + } + + if (other > 0) { + log.log("%6d: other/unrecognized%n", other); + } + + for (var line : log.getErrors()) { + System.err.println(line); + } + } + + @Override + public boolean isOK() { + return counts.isEmpty() && (other == 0); + } + + @Override + public void close() { + if (!isOK()) { + report(); + throw new RuntimeException("Found HTML files with missing doctype declaration"); + } + } +} diff --git a/test/docs/jdk/javadoc/doccheck/doccheckutils/checkers/ExtLinkChecker.java b/test/docs/jdk/javadoc/doccheck/doccheckutils/checkers/ExtLinkChecker.java new file mode 100644 index 00000000000..7e6c5a8ed5a --- /dev/null +++ b/test/docs/jdk/javadoc/doccheck/doccheckutils/checkers/ExtLinkChecker.java @@ -0,0 +1,220 @@ +/* + * 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 doccheckutils.checkers; + + +import doccheckutils.HtmlChecker; +import doccheckutils.Log; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.text.MessageFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * Checks the external links referenced in HTML files. + */ +public class ExtLinkChecker implements HtmlChecker, AutoCloseable { + private static final Path testBasePath = Path.of(System.getProperty("test.src")); + private static final Set extLinks = new HashSet<>(); + + private static final String currentVersion = String.valueOf(Runtime.version().feature()); + + static { + String input = null; + try { + input = Files.readString(testBasePath.getParent().resolve("ExtLinksJdk.txt")); + } catch (IOException e) { + throw new RuntimeException(e); + } + extLinks.addAll(input.lines() + .filter(line -> !line.startsWith("#")) + .map(line -> line.replaceAll("\\@\\@JAVASE_VERSION\\@\\@", currentVersion)) + .collect(Collectors.toUnmodifiableSet())); + } + + private final Log log; + private final Map> allURIs; + private int badURIs; + private Path currFile; + + public ExtLinkChecker() { + this.log = new Log(); + allURIs = new TreeMap<>(); + } + + @Override + public void startFile(Path path) { + currFile = path.toAbsolutePath().normalize(); + } + + @Override + public void endFile() { + } + + @Override + public void xml(int line, Map attrs) { + } + + @Override + public void docType(int line, String doctype) { + } + + @Override + @SuppressWarnings("fallthrough") + public void startElement(int line, String name, Map attrs, boolean selfClosing) { + switch (name) { + case "a": + case "link": + String href = attrs.get("href"); + if (href != null) { + foundReference(line, href); + } + break; + } + } + + @Override + public void endElement(int line, String name) { + } + + private void foundReference(int line, String ref) { + try { + String uriPath = ref; + String fragment = null; + + // The checker runs into a problem with links that have more than one hash character. + // You cannot create a URI unless the second hash is escaped. + + int firstHashIndex = ref.indexOf('#'); + int lastHashIndex = ref.lastIndexOf('#'); + if (firstHashIndex != -1 && firstHashIndex != lastHashIndex) { + uriPath = ref.substring(0, firstHashIndex); + fragment = ref.substring(firstHashIndex + 1).replace("#", "%23"); + } else if (firstHashIndex != -1) { + uriPath = ref.substring(0, firstHashIndex); + fragment = ref.substring(firstHashIndex + 1); + } + + URI uri = new URI(uriPath); + if (fragment != null) { + uri = new URI(uri + "#" + fragment); + } + + if (uri.isAbsolute()) { + if (Objects.equals(uri.getScheme(), "javascript")) { + // ignore JavaScript URIs + return; + } + String rawFragment = uri.getRawFragment(); + URI noFrag = new URI(uri.toString().replaceAll("#\\Q" + rawFragment + "\\E$", "")); + allURIs.computeIfAbsent(noFrag, _ -> new LinkedHashSet<>()).add(currFile); + } + } catch (URISyntaxException e) { + log.log(currFile, line, "invalid URI: " + e); + } + } + + @Override + public void report() { + checkURIs(); + } + + @Override + public boolean isOK() { + return badURIs == 0; + } + + @Override + public void close() { + report(); + } + + private void checkURIs() { + System.err.println("ExtLinkChecker: checking external links"); + allURIs.forEach(this::checkURI); + System.err.println("ExtLinkChecker: finished checking external links"); + } + + private void checkURI(URI uri, Set files) { + try { + switch (uri.getScheme()) { + case "ftp": + case "http": + case "https": + isVettedLink(uri, files); + break; + default: + warning(files, uri); + } + } catch (Throwable t) { + badURIs++; + error(files, uri, t); + } + } + + private void isVettedLink(URI uri, Set files) { + if (!extLinks.contains(uri.toString())) { + System.err.println(MessageFormat.format(""" + The external link {0} needs to be added to the whitelist test/docs/jdk/javadoc/doccheck/ExtLinksJdk.txt in order to be checked regularly\s + The link is present in: + {1}\n + """, uri, files.stream().map(Path::toString).collect(Collectors.joining("\n ")))); + } + } + + private void warning(Set files, Object... args) { + Iterator iter = files.iterator(); + Path first = iter.next(); + log.log(String.valueOf(first), "URI not supported: %s", args); + reportAlsoFoundIn(iter); + } + + private void error(Set files, Object... args) { + Iterator iter = files.iterator(); + Path first = iter.next(); + log.log(String.valueOf(first), "Exception accessing uri: %s%n [%s]", args); + reportAlsoFoundIn(iter); + } + + private void reportAlsoFoundIn(Iterator iter) { + int MAX_EXTRA = 10; + int n = 0; + while (iter.hasNext()) { + log.log(" Also found in %s", log.relativize(iter.next())); + if (n++ == MAX_EXTRA) { + int rest = 0; + while (iter.hasNext()) { + iter.next(); + rest++; + } + log.log(" ... and %d more", rest); + } + } + } +} diff --git a/test/docs/jdk/javadoc/doccheck/doccheckutils/checkers/LinkChecker.java b/test/docs/jdk/javadoc/doccheck/doccheckutils/checkers/LinkChecker.java new file mode 100644 index 00000000000..62ead5a25d3 --- /dev/null +++ b/test/docs/jdk/javadoc/doccheck/doccheckutils/checkers/LinkChecker.java @@ -0,0 +1,440 @@ +/* + * 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 doccheckutils.checkers; + + +import doccheckutils.HtmlChecker; +import doccheckutils.Log; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.*; + +/** + * Checks the links defined by and referenced in HTML files. + */ +public class LinkChecker implements HtmlChecker { + + private final Log log; + private final Map allFiles; + private final Map allURIs; + // left for debugging + private final boolean checkInwardReferencesOnly = false; + private int files; + private int links; + private int duplicateIds; + private int missingFiles; + private int missingIds; + private int badSchemes; + private Path currFile; + private IDTable currTable; + private boolean html5; + public LinkChecker() { + this.log = new Log(); + allFiles = new HashMap<>(); + allURIs = new HashMap<>(); + } + + public void setBaseDir(Path dir) { + log.setBaseDirectory(dir); + } + + @Override + public void startFile(Path path) { + currFile = path.toAbsolutePath().normalize(); + currTable = allFiles.computeIfAbsent(currFile, p -> new IDTable(log.relativize(p))); + html5 = false; + files++; + } + + @Override + public void endFile() { + currTable.check(); + } + + + //unused + public List getUncheckedFiles() { + return allFiles.entrySet().stream() + .filter(e -> !e.getValue().checked + && e.getKey().toString().endsWith(".html") + && Files.exists(e.getKey())) + .map(Map.Entry::getKey) + .toList(); + } + + public List getMissingFiles() { + return allFiles.keySet().stream() + .filter(idTable -> !Files.exists(idTable)).toList(); + } + + @Override + public void xml(int line, Map attrs) { + } + + @Override + public void docType(int line, String doctype) { + html5 = doctype.matches("(?i)<\\?doctype\\s+html>"); + } + + @Override + @SuppressWarnings("fallthrough") + public void startElement(int line, String name, Map attrs, boolean selfClosing) { + switch (name) { + case "a": + String nameAttr = html5 ? null : attrs.get("name"); + if (nameAttr != null) { + foundAnchor(line, nameAttr); + } + // fallthrough + case "link": + String href = attrs.get("href"); + if (href != null && !checkInwardReferencesOnly) { + foundReference(line, href); + } + break; + } + + String idAttr = attrs.get("id"); + if (idAttr != null) { + foundAnchor(line, idAttr); + } + } + + @Override + public void endElement(int line, String name) { + } + + @Override + public void content(int line, String content) { + HtmlChecker.super.content(line, content); + } + + @Override + public void report() { + List pathList = getMissingFiles(); + log.log(""); + log.log("Link Checker Report"); + + if (!pathList.isEmpty()) { + log.log(""); + log.log("Missing files: (" + pathList.size() + ")"); + pathList.stream() + .sorted() + .forEach(this::reportMissingFile); + } + + int anchors = 0; + for (IDTable t : allFiles.values()) { + anchors += (int) t.map.values().stream() + .filter(e -> !e.getReferences().isEmpty()) + .count(); + } + for (IDTable t : allURIs.values()) { + anchors += (int) t.map.values().stream() + .filter(e -> !e.references.isEmpty()) + .count(); + } + + log.log("Checked " + files + " files."); + log.log("Found " + links + " references to " + anchors + " anchors " + + "in " + allFiles.size() + " files and " + allURIs.size() + " other URIs."); + if (!pathList.isEmpty()) { + log.log("%6d missing files", pathList.size()); + } + if (duplicateIds > 0) { + log.log("%6d duplicate ids", duplicateIds); + + } + if (missingIds > 0) { + log.log("%6d missing ids", missingIds); + + } + + Map hostCounts = new TreeMap<>(new HostComparator()); + for (URI uri : allURIs.keySet()) { + String host = uri.getHost(); + if (host != null) { + hostCounts.put(host, hostCounts.computeIfAbsent(host, h -> 0) + 1); + } + } + +// if (hostCounts.size() > 0) { +// log.log(""); +// log.log("Hosts"); +// hostCounts.forEach((h, n) -> log.log("%6d %s", n, h)); +// } + + + for (String message : log.getErrors()) { + System.err.println(message); + } + + } + + private void reportMissingFile(Path file) { + log.log(log.relativize(file).toString()); + IDTable table = allFiles.get(file); + Set refs = new TreeSet<>(); + for (IDInfo id : table.map.values()) { + if (id.references != null) { + for (Position ref : id.references) { + refs.add(ref.path); + } + } + } + int n = 0; + int MAX_REFS = 10; + for (Path ref : refs) { + log.log(" in " + log.relativize(ref)); + if (++n == MAX_REFS) { + log.log(" ... and %d more", refs.size() - n); + break; + } + } + missingFiles++; + } + + @Override + public boolean isOK() { + return duplicateIds == 0 + && missingIds == 0 + && missingFiles == 0 + && badSchemes == 0; + } + + @Override + public void close() { + report(); + if (!isOK()) { + throw new RuntimeException( + "LinkChecker encountered errors. Duplicate IDs: " + + duplicateIds + ", Missing IDs: " + missingIds + + ", Missing Files: " + missingFiles + ", Bad Schemes: " + badSchemes); + } + } + + private void foundAnchor(int line, String name) { + currTable.addID(line, name); + } + + private void foundReference(int line, String ref) { + links++; + try { + String uriPath = ref; + String fragment = null; + + // The checker runs into a problem with links that have more than one hash character. + // You cannot create a URI unless the second hash is escaped. + + int firstHashIndex = ref.indexOf('#'); + int lastHashIndex = ref.lastIndexOf('#'); + if (firstHashIndex != -1 && firstHashIndex != lastHashIndex) { + uriPath = ref.substring(0, firstHashIndex); + fragment = ref.substring(firstHashIndex + 1).replace("#", "%23"); + } else if (firstHashIndex != -1) { + uriPath = ref.substring(0, firstHashIndex); + fragment = ref.substring(firstHashIndex + 1); + } + + URI uri = new URI(uriPath); + if (fragment != null) { + uri = new URI(uri + "#" + fragment); + } + + if (uri.isAbsolute()) { + foundReference(line, uri); + } else { + Path p; + String resolvedUriPath = uri.getPath(); + if (resolvedUriPath == null || resolvedUriPath.isEmpty()) { + p = currFile; + } else { + p = currFile.getParent().resolve(resolvedUriPath).normalize(); + } + + if (fragment != null && !fragment.isEmpty()) { + foundReference(line, p, fragment); + } + } + } catch (URISyntaxException e) { + System.err.println("Failed to create URI: " + ref); + log.log(currFile, line, "invalid URI: " + e); + } + } + + + private void foundReference(int line, Path p, String fragment) { + IDTable t = allFiles.computeIfAbsent(p, key -> new IDTable(log.relativize(key))); + t.addReference(fragment, currFile, line); + } + + private void foundReference(int line, URI uri) { + if (!isSchemeOK(uri.getScheme()) && !checkInwardReferencesOnly) { + log.log(currFile, line, "bad scheme in URI"); + badSchemes++; + } + + String fragment = uri.getRawFragment(); + if (fragment != null && !fragment.isEmpty()) { + try { + URI noFrag = new URI(uri.toString().replaceAll("#\\Q" + fragment + "\\E$", "")); + IDTable t = allURIs.computeIfAbsent(noFrag, IDTable::new); + t.addReference(fragment, currFile, line); + } catch (URISyntaxException e) { + throw new Error(e); + } + } + } + + private boolean isSchemeOK(String uriScheme) { + if (uriScheme == null) { + return true; + } + + return switch (uriScheme) { + case "ftp", "http", "https", "javascript" -> true; + default -> false; + }; + } + + static class Position implements Comparable { + Path path; + int line; + + Position(Path path, int line) { + this.path = path; + this.line = line; + } + + @Override + public int compareTo(Position o) { + int v = path.compareTo(o.path); + return v != 0 ? v : Integer.compare(line, o.line); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } else if (obj == null || getClass() != obj.getClass()) { + return false; + } else { + final Position other = (Position) obj; + return Objects.equals(this.path, other.path) + && this.line == other.line; + } + } + + @Override + public int hashCode() { + return Objects.hashCode(path) * 37 + line; + } + } + + static class IDInfo { + boolean declared; + Set references; + + Set getReferences() { + return references == null ? Collections.emptySet() : references; + } + } + + static class HostComparator implements Comparator { + @Override + public int compare(String h1, String h2) { + List l1 = new ArrayList<>(Arrays.asList(h1.split("\\."))); + Collections.reverse(l1); + String r1 = String.join(".", l1); + List l2 = new ArrayList<>(Arrays.asList(h2.split("\\."))); + Collections.reverse(l2); + String r2 = String.join(".", l2); + return r1.compareTo(r2); + } + } + + class IDTable { + private final Map map = new HashMap<>(); + private final String pathOrURI; + private boolean checked; + + IDTable(Path path) { + this.pathOrURI = path.toString(); + } + + IDTable(URI uri) { + this.pathOrURI = uri.toString(); + } + + void addID(int line, String name) { + if (checked) { + throw new IllegalStateException("Adding ID after file has been"); + } + Objects.requireNonNull(name); + IDInfo info = map.computeIfAbsent(name, _ -> new IDInfo()); + if (info.declared) { + if (info.references != null || !checkInwardReferencesOnly) { + // don't report error if we're only checking inbound references + // and there are no references to this ID. + log.log(log.relativize(currFile), line, "name already declared: " + name); + duplicateIds++; + } + } else { + info.declared = true; + } + } + + void addReference(String name, Path from, int line) { + if (checked) { + if (name != null) { + IDInfo id = map.get(name); + if (id == null || !id.declared) { + log.log(log.relativize(from), line, "id not found: " + this.pathOrURI + "#" + name); + } + } + } else { + IDInfo id = map.computeIfAbsent(name, x -> new IDInfo()); + if (id.references == null) { + id.references = new TreeSet<>(); + } + id.references.add(new Position(from, line)); + } + } + + void check() { + map.forEach((name, id) -> { + if (name != null && !id.declared) { + for (Position ref : id.references) { + log.log(log.relativize(ref.path), ref.line, "id not found: " + this.pathOrURI + "#" + name); + } + missingIds++; + } + }); + checked = true; + } + } +} diff --git a/test/docs/jdk/javadoc/doccheck/doccheckutils/checkers/TidyChecker.java b/test/docs/jdk/javadoc/doccheck/doccheckutils/checkers/TidyChecker.java new file mode 100644 index 00000000000..727e90a76e3 --- /dev/null +++ b/test/docs/jdk/javadoc/doccheck/doccheckutils/checkers/TidyChecker.java @@ -0,0 +1,259 @@ +/* + * 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 doccheckutils.checkers; + + +import doccheckutils.FileChecker; +import doccheckutils.Log; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class TidyChecker implements FileChecker, AutoCloseable { + private final Path TIDY; + final Map counts = new HashMap<>(); + final Pattern okPattern = Pattern.compile("No warnings or errors were found."); + final Pattern countPattern = Pattern.compile("([0-9]+) warnings, ([0-9]+) errors were found!.*?(Not all warnings/errors were shown.)?"); + final Pattern countPattern2 = Pattern.compile("Tidy found ([0-9]+) warning[s]? and ([0-9]+) error[s]?!.*?(Not all warnings/errors were shown.)?"); + final Pattern cssPattern = Pattern.compile("You are recommended to use CSS.*"); + final Pattern guardPattern = Pattern.compile("(line [0-9]+ column [0-9]+ - |[^:]+:[0-9]+:[0-9]+: )(Error|Warning):.*"); + + final Pattern[] patterns = { + Pattern.compile(".*Error: <.*> is not recognized!"), + Pattern.compile(".*Error: missing quote mark for attribute value"), + Pattern.compile(".*Warning: '<' \\+ '/' \\+ letter not allowed here"), + Pattern.compile(".*Warning: <.*> anchor \".*\" already defined"), + Pattern.compile(".*Warning: <.*> attribute \".*\" has invalid value \".*\""), + Pattern.compile(".*Warning: <.*> attribute \".*\" lacks value"), + Pattern.compile(".*Warning: <.*> attribute \".*\" lacks value"), + Pattern.compile(".*Warning: <.*> attribute with missing trailing quote mark"), + Pattern.compile(".*Warning: <.*> dropping value \".*\" for repeated attribute \".*\""), + Pattern.compile(".*Warning: <.*> inserting \".*\" attribute"), + Pattern.compile(".*Warning: <.*> is probably intended as "), + Pattern.compile(".*Warning: <.*> isn't allowed in <.*> elements"), + Pattern.compile(".*Warning: <.*> lacks \".*\" attribute"), + Pattern.compile(".*Warning: <.*> missing '>' for end of tag"), + Pattern.compile(".*Warning: <.*> proprietary attribute \".*\""), + Pattern.compile(".*Warning: <.*> unexpected or duplicate quote mark"), + Pattern.compile(".*Warning: id and name attribute value mismatch"), + Pattern.compile(".*Warning: cannot copy name attribute to id"), + Pattern.compile(".*Warning: escaping malformed URI reference"), + Pattern.compile(".*Warning:

proprietary attribute \"pre\""), + Pattern.compile(".*Warning: discarding unexpected <.*>"), + Pattern.compile(".*Warning: discarding unexpected "), + Pattern.compile(".*Warning: entity \".*\" doesn't end in ';'"), + Pattern.compile(".*Warning: inserting implicit <.*>"), + Pattern.compile(".*Warning: inserting missing 'title' element"), + Pattern.compile(".*Warning: missing declaration"), + Pattern.compile(".*Warning: missing <.*>"), + Pattern.compile(".*Warning: missing before <.*>"), + Pattern.compile(".*Warning: nested emphasis <.*>"), + Pattern.compile(".*Warning: plain text isn't allowed in <.*> elements"), + Pattern.compile(".*Warning: removing whitespace preceding XML Declaration"), + Pattern.compile(".*Warning: replacing

(by|with)
"), + Pattern.compile(".*Warning: replacing invalid numeric character reference .*"), + Pattern.compile(".*Warning: replacing obsolete element

with <pre>"), + Pattern.compile(".*Warning: replacing unexpected .* (by|with) </.*>"), + Pattern.compile(".*Warning: trimming empty <.*>"), + Pattern.compile(".*Warning: unescaped & or unknown entity \".*\""), + Pattern.compile(".*Warning: unescaped & which should be written as &amp;"), + Pattern.compile(".*Warning: using <br> in place of <p>"), + Pattern.compile(".*Warning: <.*> element removed from HTML5"), + Pattern.compile(".*Warning: <.*> attribute \".*\" not allowed for HTML5"), + Pattern.compile(".*Warning: The summary attribute on the <table> element is obsolete in HTML5"), + Pattern.compile(".*Warning: replacing invalid UTF-8 bytes \\(char. code U\\+.*\\)") + }; + private final Log errors; + private int files = 0; + private int ok; + private int warns; + private int errs; + private int css; + private int overflow; + + public TidyChecker() { + TIDY = initTidy(); + errors = new Log(); + } + + @Override + public void checkFiles(List<Path> sb) { + files += sb.size(); + try { + for (int i = 0; i < sb.size(); i += 1024) { + List<String> command = new ArrayList<>(); + command.add(TIDY.toString()); + command.add("-q"); + command.add("-e"); + command.add("--gnu-emacs"); + command.add("true"); + List<Path> sublist = sb.subList(i, Math.min(i + 1024, sb.size())); + for (Path p : sublist) { + command.add(p.toString()); + } + Process p = new ProcessBuilder() + .command(command) + .redirectErrorStream(true) + .start(); + try (BufferedReader r = + new BufferedReader(new InputStreamReader(p.getInputStream(), StandardCharsets.UTF_8))) { + String line; + while ((line = r.readLine()) != null) { + checkLine(line); + } + } + } + } catch (IOException e) { + throw new RuntimeException(); + } + } + + private Path initTidy() { + Path tidyExePath; + String tidyProperty = System.getProperty("tidy"); + if (tidyProperty != null) { + tidyExePath = Path.of(tidyProperty); + if (!Files.exists(tidyExePath)) { + System.err.println("tidy not found: " + tidyExePath); + } + if (!Files.isExecutable(tidyExePath)) { + System.err.println("tidy not executable: " + tidyExePath); + } + } else { + boolean isWindows = System.getProperty("os.name") + .toLowerCase(Locale.US) + .startsWith("windows"); + String tidyExe = isWindows ? "tidy.exe" : "tidy"; + Optional<Path> p = Stream.of(System.getenv("PATH") + .split(File.pathSeparator)) + .map(Path::of) + .map(d -> d.resolve(tidyExe)) + .filter(Files::exists) + .filter(Files::isExecutable) + .findFirst(); + if (p.isPresent()) { + tidyExePath = p.get(); + } else { + System.err.println("tidy not found on PATH"); + return Path.of("tidy"); //non-null placeholder return; exception would be better + } + } + + try { + Process p = new ProcessBuilder() + .command(tidyExePath.toString(), "-version") + .redirectErrorStream(true) + .start(); + try (BufferedReader r = + new BufferedReader(new InputStreamReader(p.getInputStream(), StandardCharsets.UTF_8))) { + List<String> lines = r.lines().collect(Collectors.toList()); + // Look for a line containing "version" and a dotted identifier beginning 5. + // If not found, look for known old/bad versions, to report in error message + Pattern version = Pattern.compile("version.* [5678]\\.\\d+(\\.\\d+)"); + if (lines.stream().noneMatch(line -> version.matcher(line).find())) { + Pattern oldVersion = Pattern.compile("2006"); // 2006 implies old macOS version + String lineSep = System.lineSeparator(); + String message = lines.stream().anyMatch(line -> oldVersion.matcher(line).find()) + ? "old version of 'tidy' found on the PATH\n" + : "could not determine the version of 'tidy' on the PATH\n"; + System.err.println(message + String.join(lineSep, lines)); + } + } + } catch (IOException e) { + System.err.println("Could not execute 'tidy -version': " + e); + } + + return tidyExePath; + } + + @Override + public void report() { + if (files > 0) { + System.err.println("Tidy found errors in the generated HTML"); + if (!errors.noErrors()) { + for (String s : errors.getErrors()) { + System.err.println(s); + } + System.err.println("Tidy output end."); + System.err.println(); + System.err.println(); + throw new RuntimeException("Tidy found errors in the generated HTML"); + } + } + } + + @Override + public boolean isOK() { + return (ok == files) + && (overflow == 0) + && (errs == 0) + && (warns == 0) + && (css == 0); + } + + void checkLine(String line) { + Matcher m; + if (okPattern.matcher(line).matches()) { + ok++; + } else if ((m = countPattern.matcher(line)).matches() || (m = countPattern2.matcher(line)).matches()) { + warns += Integer.parseInt(m.group(1)); + errs += Integer.parseInt(m.group(2)); + if (m.group(3) != null) + overflow++; + } else if (guardPattern.matcher(line).matches()) { + boolean found = false; + for (Pattern p : patterns) { + if (p.matcher(line).matches()) { + errors.log("%s", line); + found = true; + count(p); + break; + } + } + if (!found) + errors.log("unrecognized line: " + line); + } else if (cssPattern.matcher(line).matches()) { + css++; + } + } + + void count(Pattern p) { + Integer i = counts.get(p); + counts.put(p, (i == null) ? 1 : i + 1); + } + + @Override + public void close() { + report(); + } +} diff --git a/test/hotspot/jtreg/ProblemList-Virtual.txt b/test/hotspot/jtreg/ProblemList-Virtual.txt index 24a1d0c7c5b..09f79165980 100644 --- a/test/hotspot/jtreg/ProblemList-Virtual.txt +++ b/test/hotspot/jtreg/ProblemList-Virtual.txt @@ -87,19 +87,10 @@ vmTestbase/nsk/jdi/ExceptionEvent/catchLocation/location002/TestDescription.java vmTestbase/nsk/jdi/VMOutOfMemoryException/VMOutOfMemoryException001/VMOutOfMemoryException001.java 8285417 generic-all ### -# The test first suspends a vthread and all the carriers and then it resumes the vthread expecting it -# to run to completion. In mainline it only works because the suspension step happens while the vthread is -# pinned to the carrier blocked on synchronized. So the carrier only actually suspends on the next unmount -# transition which in this test happens once the vthread has finished executing the expected code. - +# Fails because resume of a virtual thread is not enough to allow the virtual thread +# to make progress when all other threads are currently suspended. vmTestbase/nsk/jdi/ThreadReference/isSuspended/issuspended002/TestDescription.java 8338713 generic-all -### -# The test sends a StopThread to a vthread expecting that is currently pinned to the carrier blocked on -# synchronized. Since the vthread is now unmounted StopThread returns JVMTI_ERROR_OPAQUE_FRAME error. - -vmTestbase/nsk/jdb/kill/kill001/kill001.java 8338714 generic-all - ### # Fails on Windows because of additional memory allocation. diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index 08678af706d..a466b4c9321 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -71,6 +71,8 @@ compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/VirtualObjectDebugInf compiler/floatingpoint/TestSubnormalFloat.java 8317810 generic-i586 compiler/floatingpoint/TestSubnormalDouble.java 8317810 generic-i586 +compiler/startup/StartupOutput.java 8347406 generic-x64 + compiler/codecache/CodeCacheFullCountTest.java 8332954 generic-all compiler/interpreter/Test6833129.java 8335266 generic-i586 @@ -116,10 +118,6 @@ runtime/ErrorHandling/MachCodeFramesInErrorFile.java 8313315 linux-ppc64le runtime/cds/appcds/customLoader/HelloCustom_JFR.java 8241075 linux-all,windows-x64 runtime/NMT/VirtualAllocCommitMerge.java 8309698 linux-s390x -# Fails with +UseCompactObjectHeaders on aarch64 -runtime/cds/appcds/SharedBaseAddress.java 8340212 linux-aarch64,macosx-aarch64 -runtime/cds/SharedBaseAddress.java 8340212 linux-aarch64,macosx-aarch64 - applications/jcstress/copy.java 8229852 linux-all containers/docker/TestJcmd.java 8278102 linux-all diff --git a/test/hotspot/jtreg/compiler/arraycopy/TestArrayCopyNoInit.java b/test/hotspot/jtreg/compiler/arraycopy/TestArrayCopyNoInit.java index 828fb5ace99..c85a0d6ac1c 100644 --- a/test/hotspot/jtreg/compiler/arraycopy/TestArrayCopyNoInit.java +++ b/test/hotspot/jtreg/compiler/arraycopy/TestArrayCopyNoInit.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,11 +23,14 @@ /* * @test - * @bug 8064703 + * @bug 8064703 8347006 * @summary Deoptimization between array allocation and arraycopy may result in non initialized array * * @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement -XX:TypeProfileLevel=020 * compiler.arraycopy.TestArrayCopyNoInit + * @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement -XX:TypeProfileLevel=020 + * -XX:+UnlockExperimentalVMOptions -XX:+UseCompactObjectHeaders -XX:-UseTLAB + * compiler.arraycopy.TestArrayCopyNoInit */ package compiler.arraycopy; diff --git a/test/hotspot/jtreg/compiler/c2/TestSerialAdditions.java b/test/hotspot/jtreg/compiler/c2/TestSerialAdditions.java deleted file mode 100644 index c52f17dd975..00000000000 --- a/test/hotspot/jtreg/compiler/c2/TestSerialAdditions.java +++ /dev/null @@ -1,257 +0,0 @@ -/* - * Copyright (c) 2024 Red Hat 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 compiler.c2; - -import compiler.lib.ir_framework.Test; -import compiler.lib.ir_framework.*; -import jdk.test.lib.Asserts; -import jdk.test.lib.Utils; - -import java.util.Random; - -/* - * @test - * @bug 8325495 - * @summary C2 should optimize for series of Add of unique value. e.g., a + a + ... + a => a*n - * @library /test/lib / - * @run driver compiler.c2.TestSerialAdditions - */ -public class TestSerialAdditions { - private static final Random RNG = Utils.getRandomInstance(); - - public static void main(String[] args) { - TestFramework.run(); - } - - @Run(test = { - "addTo2", - "addTo3", - "addTo4", - "shiftAndAddTo4", - "mulAndAddTo4", - "addTo5", - "addTo6", - "addTo7", - "addTo8", - "addTo16", - "addAndShiftTo16", - "addTo42", - "mulAndAddTo42", - "mulAndAddToMax", - "mulAndAddToOverflow", - "mulAndAddToZero", - "mulAndAddToMinus1", - "mulAndAddToMinus42" - }) - private void runIntTests() { - for (int a : new int[] { 0, 1, Integer.MIN_VALUE, Integer.MAX_VALUE, RNG.nextInt() }) { - Asserts.assertEQ(a * 2, addTo2(a)); - Asserts.assertEQ(a * 3, addTo3(a)); - Asserts.assertEQ(a * 4, addTo4(a)); - Asserts.assertEQ(a * 4, shiftAndAddTo4(a)); - Asserts.assertEQ(a * 4, mulAndAddTo4(a)); - Asserts.assertEQ(a * 5, addTo5(a)); - Asserts.assertEQ(a * 6, addTo6(a)); - Asserts.assertEQ(a * 7, addTo7(a)); - Asserts.assertEQ(a * 8, addTo8(a)); - Asserts.assertEQ(a * 16, addTo16(a)); - Asserts.assertEQ(a * 16, addAndShiftTo16(a)); - Asserts.assertEQ(a * 42, addTo42(a)); - Asserts.assertEQ(a * 42, mulAndAddTo42(a)); - Asserts.assertEQ(a * Integer.MAX_VALUE, mulAndAddToMax(a)); - Asserts.assertEQ(a * Integer.MIN_VALUE, mulAndAddToOverflow(a)); - Asserts.assertEQ(0, mulAndAddToZero(a)); - Asserts.assertEQ(a * -1, mulAndAddToMinus1(a)); - Asserts.assertEQ(a * -42, mulAndAddToMinus42(a)); - } - } - - @Run(test = { - "mulAndAddToIntOverflowL", - "mulAndAddToMaxL", - "mulAndAddToOverflowL" - }) - private void runLongTests() { - for (long a : new long[] { 0, 1, Long.MIN_VALUE, Long.MAX_VALUE, RNG.nextLong() }) { - Asserts.assertEQ(a * (Integer.MAX_VALUE + 1L), mulAndAddToIntOverflowL(a)); - Asserts.assertEQ(a * Long.MAX_VALUE, mulAndAddToMaxL(a)); - Asserts.assertEQ(a * Long.MIN_VALUE, mulAndAddToOverflowL(a)); - } - } - - // ----- integer tests ----- - @Test - @IR(counts = { IRNode.ADD_I, "1" }) - @IR(failOn = IRNode.LSHIFT_I) - private static int addTo2(int a) { - return a + a; // Simple additions like a + a should be kept as-is - } - - @Test - @IR(counts = { IRNode.ADD_I, "1", IRNode.LSHIFT_I, "1" }) - private static int addTo3(int a) { - return a + a + a; // a*3 => (a<<1) + a - } - - @Test - @IR(failOn = IRNode.ADD_I) - @IR(counts = { IRNode.LSHIFT_I, "1" }) - private static int addTo4(int a) { - return a + a + a + a; // a*4 => a<<2 - } - - @Test - @IR(failOn = IRNode.ADD_I) - @IR(counts = { IRNode.LSHIFT_I, "1" }) - private static int shiftAndAddTo4(int a) { - return (a << 1) + a + a; // a*2 + a + a => a*3 + a => a*4 => a<<2 - } - - @Test - @IR(failOn = IRNode.ADD_I) - @IR(counts = { IRNode.LSHIFT_I, "1" }) - private static int mulAndAddTo4(int a) { - return a * 3 + a; // a*4 => a<<2 - } - - @Test - @IR(counts = { IRNode.ADD_I, "1", IRNode.LSHIFT_I, "1" }) - private static int addTo5(int a) { - return a + a + a + a + a; // a*5 => (a<<2) + a - } - - @Test - @IR(counts = { IRNode.ADD_I, "1", IRNode.LSHIFT_I, "2" }) - private static int addTo6(int a) { - return a + a + a + a + a + a; // a*6 => (a<<1) + (a<<2) - } - - @Test - @IR(failOn = IRNode.ADD_I) - @IR(counts = { IRNode.LSHIFT_I, "1", IRNode.SUB_I, "1" }) - private static int addTo7(int a) { - return a + a + a + a + a + a + a; // a*7 => (a<<3) - a - } - - @Test - @IR(failOn = IRNode.ADD_I) - @IR(counts = { IRNode.LSHIFT_I, "1" }) - private static int addTo8(int a) { - return a + a + a + a + a + a + a + a; // a*8 => a<<3 - } - - @Test - @IR(failOn = IRNode.ADD_I) - @IR(counts = { IRNode.LSHIFT_I, "1" }) - private static int addTo16(int a) { - return a + a + a + a + a + a + a + a + a + a - + a + a + a + a + a + a; // a*16 => a<<4 - } - - @Test - @IR(failOn = IRNode.ADD_I) - @IR(counts = { IRNode.LSHIFT_I, "1" }) - private static int addAndShiftTo16(int a) { - return (a + a) << 3; // a<<(3 + 1) => a<<4 - } - - @Test - @IR(failOn = IRNode.ADD_I) - @IR(counts = { IRNode.MUL_I, "1" }) - private static int addTo42(int a) { - return a + a + a + a + a + a + a + a + a + a - + a + a + a + a + a + a + a + a + a + a - + a + a + a + a + a + a + a + a + a + a - + a + a + a + a + a + a + a + a + a + a - + a + a; // a*42 - } - - @Test - @IR(failOn = IRNode.ADD_I) - @IR(counts = { IRNode.MUL_I, "1" }) - private static int mulAndAddTo42(int a) { - return a * 40 + a + a; // a*41 + a => a*42 - } - - private static final int INT_MAX_MINUS_ONE = Integer.MAX_VALUE - 1; - - @Test - @IR(failOn = IRNode.ADD_I) - @IR(counts = { IRNode.LSHIFT_I, "1", IRNode.SUB_I, "1" }) - private static int mulAndAddToMax(int a) { - return a * INT_MAX_MINUS_ONE + a; // a*MAX => a*(MIN-1) => a*MIN - a => (a<<31) - a - } - - @Test - @IR(failOn = IRNode.ADD_I) - @IR(counts = { IRNode.LSHIFT_I, "1" }) - private static int mulAndAddToOverflow(int a) { - return a * Integer.MAX_VALUE + a; // a*(MAX+1) => a*(MIN) => a<<31 - } - - @Test - @IR(failOn = IRNode.ADD_I) - @IR(counts = { IRNode.CON_I, "1" }) - private static int mulAndAddToZero(int a) { - return a * -1 + a; // 0 - } - - @Test - @IR(failOn = IRNode.ADD_I) - @IR(counts = { IRNode.LSHIFT_I, "1", IRNode.SUB_I, "1" }) - private static int mulAndAddToMinus1(int a) { - return a * -2 + a; // a*-1 => a - (a<<1) - } - - @Test - @IR(failOn = IRNode.ADD_I) - @IR(counts = { IRNode.MUL_I, "1" }) - private static int mulAndAddToMinus42(int a) { - return a * -43 + a; // a*-42 - } - - // --- long tests --- - @Test - @IR(failOn = IRNode.ADD_L) - @IR(counts = { IRNode.LSHIFT_L, "1" }) - private static long mulAndAddToIntOverflowL(long a) { - return a * Integer.MAX_VALUE + a; // a*(INT_MAX+1) - } - - private static final long LONG_MAX_MINUS_ONE = Long.MAX_VALUE - 1; - - @Test - @IR(failOn = IRNode.ADD_L) - @IR(counts = { IRNode.LSHIFT_L, "1", IRNode.SUB_L, "1" }) - private static long mulAndAddToMaxL(long a) { - return a * LONG_MAX_MINUS_ONE + a; // a*MAX => a*(MIN-1) => a*MIN - 1 => (a<<63) - 1 - } - - @Test - @IR(failOn = IRNode.ADD_L) - @IR(counts = { IRNode.LSHIFT_L, "1" }) - private static long mulAndAddToOverflowL(long a) { - return a * Long.MAX_VALUE + a; // a*(MAX+1) => a*(MIN) => a<<63 - } -} diff --git a/test/hotspot/jtreg/compiler/c2/gvn/TestBoolNodeGVN.java b/test/hotspot/jtreg/compiler/c2/gvn/TestBoolNodeGVN.java index 3f2fe7ecf05..384dc6f8f11 100644 --- a/test/hotspot/jtreg/compiler/c2/gvn/TestBoolNodeGVN.java +++ b/test/hotspot/jtreg/compiler/c2/gvn/TestBoolNodeGVN.java @@ -56,27 +56,47 @@ public static boolean testShouldReplaceCpmUCase1(int x, int m) { @Test @Arguments(values = {Argument.DEFAULT, Argument.DEFAULT}) @IR(failOn = IRNode.CMP_U, - phase = CompilePhase.AFTER_PARSING, - applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"}) + phase = CompilePhase.AFTER_PARSING, + applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"}) public static boolean testShouldReplaceCpmUCase2(int x, int m) { return !(Integer.compareUnsigned((m & x), m) > 0); } @Test - @Arguments(values = {Argument.DEFAULT, Argument.DEFAULT}) + @Arguments(values = {Argument.DEFAULT, Argument.RANDOM_EACH}) @IR(failOn = IRNode.CMP_U, - phase = CompilePhase.AFTER_PARSING, - applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"}) + phase = CompilePhase.AFTER_PARSING, + applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"}) public static boolean testShouldReplaceCpmUCase3(int x, int m) { + m = Math.max(0, m); return Integer.compareUnsigned((x & m), m + 1) < 0; } @Test - @Arguments(values = {Argument.DEFAULT, Argument.DEFAULT}) + @Arguments(values = {Argument.DEFAULT, Argument.RANDOM_EACH}) @IR(failOn = IRNode.CMP_U, - phase = CompilePhase.AFTER_PARSING, - applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"}) + phase = CompilePhase.AFTER_PARSING, + applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"}) public static boolean testShouldReplaceCpmUCase4(int x, int m) { + m = Math.max(0, m); + return Integer.compareUnsigned((m & x), m + 1) < 0; + } + + @Test + @Arguments(values = {Argument.DEFAULT, Argument.DEFAULT}) + @IR(counts = {IRNode.CMP_U, "1"}, // m could be -1 and thus optimization cannot be applied + phase = CompilePhase.AFTER_PARSING, + applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"}) + public static boolean testShouldNotReplaceCpmUCase1(int x, int m) { + return Integer.compareUnsigned((x & m), m + 1) < 0; + } + + @Test + @Arguments(values = {Argument.DEFAULT, Argument.DEFAULT}) + @IR(counts = {IRNode.CMP_U, "1"}, // m could be -1 and thus optimization cannot be applied + phase = CompilePhase.AFTER_PARSING, + applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"}) + public static boolean testShouldNotReplaceCpmUCase2(int x, int m) { return Integer.compareUnsigned((m & x), m + 1) < 0; } @@ -92,8 +112,8 @@ public static boolean testShouldHaveCpmUCase1(int x, int m) { @Test @Arguments(values = {Argument.DEFAULT, Argument.DEFAULT}) @IR(counts = {IRNode.CMP_U, "1"}, - phase = CompilePhase.AFTER_PARSING, - applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"}) + phase = CompilePhase.AFTER_PARSING, + applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"}) public static boolean testShouldHaveCpmUCase2(int x, int m) { return !(Integer.compareUnsigned((m & x), m - 1) > 0); } @@ -101,8 +121,8 @@ public static boolean testShouldHaveCpmUCase2(int x, int m) { @Test @Arguments(values = {Argument.DEFAULT, Argument.DEFAULT}) @IR(counts = {IRNode.CMP_U, "1"}, - phase = CompilePhase.AFTER_PARSING, - applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"}) + phase = CompilePhase.AFTER_PARSING, + applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"}) public static boolean testShouldHaveCpmUCase3(int x, int m) { return Integer.compareUnsigned((x & m), m + 2) < 0; } @@ -110,22 +130,23 @@ public static boolean testShouldHaveCpmUCase3(int x, int m) { @Test @Arguments(values = {Argument.DEFAULT, Argument.DEFAULT}) @IR(counts = {IRNode.CMP_U, "1"}, - phase = CompilePhase.AFTER_PARSING, - applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"}) + phase = CompilePhase.AFTER_PARSING, + applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"}) public static boolean testShouldHaveCpmUCase4(int x, int m) { return Integer.compareUnsigned((m & x), m + 2) < 0; } private static void testCorrectness() { int[] values = { - 0, 1, 5, 8, 16, 42, 100, new Random().nextInt(0, Integer.MAX_VALUE), Integer.MAX_VALUE + -100, -42, -16, -8, -5, -1, 0, 1, 5, 8, 16, 42, 100, + new Random().nextInt(), Integer.MAX_VALUE, Integer.MIN_VALUE }; for (int x : values) { for (int m : values) { - if (!testShouldReplaceCpmUCase1(x, m) | - !testShouldReplaceCpmUCase2(x, m) | - !testShouldReplaceCpmUCase3(x, m) | + if (!testShouldReplaceCpmUCase1(x, m) || + !testShouldReplaceCpmUCase2(x, m) || + !testShouldReplaceCpmUCase3(x, m) || !testShouldReplaceCpmUCase4(x, m)) { throw new RuntimeException("Bad result for x = " + x + " and m = " + m + ", expected always true"); } diff --git a/test/hotspot/jtreg/compiler/ciReplay/CiReplayBase.java b/test/hotspot/jtreg/compiler/ciReplay/CiReplayBase.java index a974a09d615..017242c6d9e 100644 --- a/test/hotspot/jtreg/compiler/ciReplay/CiReplayBase.java +++ b/test/hotspot/jtreg/compiler/ciReplay/CiReplayBase.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -71,6 +71,7 @@ public abstract class CiReplayBase { "-XX:-BackgroundCompilation", "-XX:CompileCommand=inline,java.io.PrintStream::*", "-XX:+IgnoreUnrecognizedVMOptions", "-XX:TypeProfileLevel=222", // extra profile data as a stress test "-XX:+CICountNative", "-XX:CICrashAt=1", "-XX:+DumpReplayDataOnError", + "-XX:-SegmentedCodeCache", REPLAY_FILE_OPTION}; private static final String[] REPLAY_OPTIONS = new String[]{DISABLE_COREDUMP_ON_CRASH, "-XX:+IgnoreUnrecognizedVMOptions", "-XX:TypeProfileLevel=222", diff --git a/test/hotspot/jtreg/compiler/codecache/CheckSegmentedCodeCache.java b/test/hotspot/jtreg/compiler/codecache/CheckSegmentedCodeCache.java index ecdb415843b..139ea6d76a2 100644 --- a/test/hotspot/jtreg/compiler/codecache/CheckSegmentedCodeCache.java +++ b/test/hotspot/jtreg/compiler/codecache/CheckSegmentedCodeCache.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -189,17 +189,8 @@ public static void main(String[] args) throws Exception { // Fails if not enough space for VM internal code long minUseSpace = WHITE_BOX.getUintxVMFlag("CodeCacheMinimumUseSpace"); - long nMethodSizeLimit = WHITE_BOX.getIntxVMFlag("NMethodSizeLimit"); - long codeEntryAlignment = WHITE_BOX.getIntxVMFlag("CodeEntryAlignment"); - long c1MinCodeCacheSize = 11 * nMethodSizeLimit / 10; - long c2MinCodeCacheSize = 2048 /* PhaseOutput::MAX_inst_size */ + - 128 /* PhaseOutput::MAX_stubs_size */ + - 4 * 1024 /* initial_const_capacity */ + - 2 * Math.max(64, codeEntryAlignment) /* 2 * CodeSection::end_slop() */ + - 2 * 128 /* sizeof(relocInfo) * PhaseOutput::MAX_locs_size */; - // minimum size: CompilerConfig::min_code_cache_size = - // CodeCacheMinimumUseSpace DEBUG_ONLY(* 3) + Compiler::code_buffer_size() + C2Compiler::initial_code_buffer_size()) - long minSize = minUseSpace * (Platform.isDebugBuild() ? 3 : 1) + c1MinCodeCacheSize + c2MinCodeCacheSize; + // minimum size: CodeCacheMinimumUseSpace DEBUG_ONLY(* 3) + long minSize = (Platform.isDebugBuild() ? 3 : 1) * minUseSpace; pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:+SegmentedCodeCache", "-XX:NonNMethodCodeHeapSize=" + minSize, "-XX:ReservedCodeCacheSize=" + minSize, diff --git a/test/hotspot/jtreg/compiler/vectorization/TestReplicateAtConv.java b/test/hotspot/jtreg/compiler/vectorization/TestReplicateAtConv.java index e77b474bf66..74ae97cc7ee 100644 --- a/test/hotspot/jtreg/compiler/vectorization/TestReplicateAtConv.java +++ b/test/hotspot/jtreg/compiler/vectorization/TestReplicateAtConv.java @@ -23,9 +23,10 @@ /** * @test - * @bug 8341834 - * @summary C2 compilation fails with "bad AD file" due to Replicate + * @bug 8341834 8343747 + * @summary Replicate node at a VectorCast (ConvL2I) causes superword to fail * @run main/othervm -XX:CompileCommand=compileonly,TestReplicateAtConv::test -Xcomp TestReplicateAtConv + * @run main/othervm -XX:CompileCommand=compileonly,TestReplicateAtConv::test -Xcomp -XX:MaxVectorSize=8 TestReplicateAtConv */ public class TestReplicateAtConv { diff --git a/test/hotspot/jtreg/runtime/CompressedOops/CompressedClassPointersEncodingScheme.java b/test/hotspot/jtreg/runtime/CompressedOops/CompressedClassPointersEncodingScheme.java index 665c4cb8b9f..6a7ab088fac 100644 --- a/test/hotspot/jtreg/runtime/CompressedOops/CompressedClassPointersEncodingScheme.java +++ b/test/hotspot/jtreg/runtime/CompressedOops/CompressedClassPointersEncodingScheme.java @@ -71,6 +71,33 @@ private static void test(long forceAddress, boolean COH, long classSpaceSize, lo output.shouldContain("Narrow klass base: " + expectedEncodingBaseString + ", Narrow klass shift: " + expectedEncodingShift); } + private static void testFailure(String forceAddressString) throws IOException { + ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( + "-Xshare:off", // to make CompressedClassSpaceBaseAddress work + "-XX:+UnlockDiagnosticVMOptions", + "-XX:CompressedClassSpaceBaseAddress=" + forceAddressString, + "-Xmx128m", + "-Xlog:metaspace*", + "-version"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + + output.reportDiagnosticSummary(); + + // We ignore cases where we were not able to map at the force address + if (!output.contains("Successfully forced class space address to " + forceAddressString)) { + throw new SkippedException("Skipping because we cannot force ccs to " + forceAddressString); + } + + if (Platform.isAArch64()) { + output.shouldHaveExitValue(1); + output.shouldContain("Error occurred during initialization of VM"); + output.shouldContain("CompressedClassSpaceBaseAddress=" + forceAddressString + + " given with shift 0, cannot be used to encode class pointers"); + } else { + output.shouldHaveExitValue(0); + } + } + final static long K = 1024; final static long M = K * 1024; final static long G = M * 1024; @@ -123,5 +150,9 @@ public static void main(String[] args) throws Exception { expectedShift = 10; test(forceAddress, true, ccsSize, forceAddress, expectedShift); } + + // Test failure for -XX:CompressedClassBaseAddress and -Xshare:off + testFailure("0x0000040001000000"); + } } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/CreateAOTCacheVerifyError.java b/test/hotspot/jtreg/runtime/cds/appcds/CreateAOTCacheVerifyError.java new file mode 100644 index 00000000000..c478fad7cc2 --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/appcds/CreateAOTCacheVerifyError.java @@ -0,0 +1,49 @@ +/* + * 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 8346457 + * @summary VM should not crash during AOT cache creation when encountering a + * class with VerifyError. + * @requires vm.cds + * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds/test-classes + * @compile test-classes/BadLookupSwitch.jcod + * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar badlookupswitch.jar BadLookupSwitch + * @run driver CreateAOTCacheVerifyError + */ + +import jdk.test.lib.helpers.ClassFileInstaller; +import jdk.test.lib.process.OutputAnalyzer; + +public class CreateAOTCacheVerifyError { + + public static void main(String[] args) throws Exception { + String appJar = ClassFileInstaller.getJarPath("badlookupswitch.jar"); + String classList[] = { BadLookupSwitch.class.getName() }; + OutputAnalyzer out = TestCommon.testDump(appJar, classList); + out.shouldContain("Preload Warning: Verification failed for BadLookupSwitch"); + out.shouldHaveExitValue(0); + } +} diff --git a/test/hotspot/jtreg/runtime/cds/appcds/LambdaWithUseImplMethodHandle.java b/test/hotspot/jtreg/runtime/cds/appcds/LambdaWithUseImplMethodHandle.java index 360fce5879a..0c747168945 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/LambdaWithUseImplMethodHandle.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/LambdaWithUseImplMethodHandle.java @@ -27,6 +27,9 @@ * @bug 8290417 * @summary CDS cannot archive lambda proxy with useImplMethodHandle * @requires vm.cds + * @requires vm.cds.supports.aot.class.linking + * @comment work around JDK-8345635 + * @requires !vm.jvmci.enabled * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds /test/hotspot/jtreg/runtime/cds/appcds/test-classes * @build pkg1.BaseWithProtectedMethod * @build pkg2.Child diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/BulkLoaderTest.java b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/BulkLoaderTest.java index 6e7473c59c1..25361403481 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/BulkLoaderTest.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/BulkLoaderTest.java @@ -29,6 +29,8 @@ /* * @test id=static * @requires vm.cds.supports.aot.class.linking + * @comment work around JDK-8345635 + * @requires !vm.jvmci.enabled * @library /test/jdk/lib/testlibrary /test/lib * @build InitiatingLoaderTester * @build BulkLoaderTest @@ -39,6 +41,8 @@ /* * @test id=dynamic * @requires vm.cds.supports.aot.class.linking + * @comment work around JDK-8345635 + * @requires !vm.jvmci.enabled * @library /test/jdk/lib/testlibrary /test/lib * @build InitiatingLoaderTester * @build jdk.test.whitebox.WhiteBox BulkLoaderTest diff --git a/test/hotspot/jtreg/runtime/cds/appcds/cacheObject/ArchiveHeapTestClass.java b/test/hotspot/jtreg/runtime/cds/appcds/cacheObject/ArchiveHeapTestClass.java index 1603d8430b2..ca5a08d20af 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/cacheObject/ArchiveHeapTestClass.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/cacheObject/ArchiveHeapTestClass.java @@ -27,6 +27,9 @@ * @bug 8214781 8293187 * @summary Test for the -XX:ArchiveHeapTestClass flag * @requires vm.debug == true & vm.cds.write.archived.java.heap + * @requires vm.cds.supports.aot.class.linking + * @comment work around JDK-8345635 + * @requires !vm.jvmci.enabled * @modules java.logging * @library /test/jdk/lib/testlibrary /test/lib * /test/hotspot/jtreg/runtime/cds/appcds diff --git a/test/hotspot/jtreg/runtime/cds/appcds/resolvedConstants/AOTLinkedLambdas.java b/test/hotspot/jtreg/runtime/cds/appcds/resolvedConstants/AOTLinkedLambdas.java index 5fb0a30cd61..d015498ed04 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/resolvedConstants/AOTLinkedLambdas.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/resolvedConstants/AOTLinkedLambdas.java @@ -28,6 +28,8 @@ * @bug 8340836 * @requires vm.cds * @requires vm.cds.supports.aot.class.linking + * @comment work around JDK-8345635 + * @requires !vm.jvmci.enabled * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds/test-classes/ * @build AOTLinkedLambdas * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar diff --git a/test/hotspot/jtreg/runtime/cds/appcds/resolvedConstants/AOTLinkedVarHandles.java b/test/hotspot/jtreg/runtime/cds/appcds/resolvedConstants/AOTLinkedVarHandles.java index 2098ebc2c71..886e0424c9a 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/resolvedConstants/AOTLinkedVarHandles.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/resolvedConstants/AOTLinkedVarHandles.java @@ -28,6 +28,8 @@ * @bug 8343245 * @requires vm.cds * @requires vm.cds.supports.aot.class.linking + * @comment work around JDK-8345635 + * @requires !vm.jvmci.enabled * @library /test/lib * @build AOTLinkedVarHandles * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar diff --git a/test/hotspot/jtreg/runtime/cds/appcds/test-classes/BadLookupSwitch.jcod b/test/hotspot/jtreg/runtime/cds/appcds/test-classes/BadLookupSwitch.jcod new file mode 100644 index 00000000000..4912479a8aa --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/appcds/test-classes/BadLookupSwitch.jcod @@ -0,0 +1,118 @@ +/* + * 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. + * + */ + +class BadLookupSwitch { + 0xCAFEBABE; + 0; + 50; + [] { // Constant Pool + ; // first element is empty + class #12; // #1 at 0x0A + class #15; // #2 at 0x0D + Method #2 #4; // #3 at 0x10 + NameAndType #6 #5; // #4 at 0x15 + Utf8 "()V"; // #5 at 0x1A + Utf8 "<init>"; // #6 at 0x20 + Utf8 "Code"; // #7 at 0x29 + Utf8 "ConstantValue"; // #8 at 0x30 + Utf8 "Exceptions"; // #9 at 0x40 + Utf8 "LineNumberTable"; // #10 at 0x4D + Utf8 "LocalVariables"; // #11 at 0x5F + Utf8 "BadLookupSwitch"; // #12 at 0x70 + Utf8 "SourceFile"; // #13 at 0x76 + Utf8 "f.java"; // #14 at 0x83 + Utf8 "java/lang/Object"; // #15 at 0x8C + Utf8 "m"; // #16 at 0x9F + Utf8 "StackMapTable"; // #17 + } // Constant Pool + + 0x0020; // access + #1;// this_cpx + #2;// super_cpx + + [0] { // Interfaces + } // Interfaces + + [0] { // fields + } // fields + + [2] { // methods + { // Member at 0xAF + 0x0001; // access + #16; // name_cpx + #5; // sig_cpx + [] { // Attributes + Attr(#7) { // Code at 0xB7 + 1; // max_stack + 1; // max_locals + Bytes[29] { + 0x04AB00000000001B; // iconst_1; +/* right: + 0x0000000200000001; // lookupswitch 27 2 1 27 2 27; + 0x0000001B00000002; + 0x0000001B; +end right */ +// wrong: + 0x0000000200000002; // lookupswitch 27 2 2 27 1 27; + 0x0000001B00000001; + 0x0000001B; +// end wrong + 0xB1; // return + }; + [0] { // Traps + } // end Traps + [] { // Attributes + Attr(#17) { // StackMap + [] { // + 255b, 28, []{O,1}, []{}; + } + } // end StackMap + } // Attributes + } // end Code + } // Attributes + } // Member + ; + { // Member at 0xD6 + 0x0000; // access + #6; // name_cpx + #5; // sig_cpx + [1] { // Attributes + Attr(#7) { // Code at 0xDE + 1; // max_stack + 1; // max_locals + Bytes[5] { + 0x2AB70003B1; + }; + [0] { // Traps + } // end Traps + [] { // Attributes + } // Attributes + } // end Code + } // Attributes + } // Member + } // methods + + [] { // Attributes + } // Attributes +} // end class diff --git a/test/hotspot/jtreg/testlibrary/ctw/Makefile b/test/hotspot/jtreg/testlibrary/ctw/Makefile index 4cf20b12e52..ea133f97621 100644 --- a/test/hotspot/jtreg/testlibrary/ctw/Makefile +++ b/test/hotspot/jtreg/testlibrary/ctw/Makefile @@ -47,12 +47,13 @@ LIB_FILES = $(shell find $(TESTLIBRARY_DIR)/jdk/test/lib/ \ $(TESTLIBRARY_DIR)/jdk/test/lib/process \ $(TESTLIBRARY_DIR)/jdk/test/lib/util \ $(TESTLIBRARY_DIR)/jtreg \ - -maxdepth 1 -name '*.java')) + -maxdepth 1 -name '*.java') WB_SRC_FILES = $(shell find $(TESTLIBRARY_DIR)/jdk/test/lib/compiler $(TESTLIBRARY_DIR)/jdk/test/whitebox -name '*.java') WB_CLASS_FILES := $(subst $(TESTLIBRARY_DIR)/,,$(WB_SRC_FILES)) WB_CLASS_FILES := $(patsubst %.java,%.class,$(WB_CLASS_FILES)) EXPORTS=--add-exports java.base/jdk.internal.jimage=ALL-UNNAMED \ --add-exports java.base/jdk.internal.misc=ALL-UNNAMED \ + --add-exports java.base/jdk.internal.module=ALL-UNNAMED \ --add-exports java.base/jdk.internal.reflect=ALL-UNNAMED \ --add-exports java.base/jdk.internal.access=ALL-UNNAMED diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/kill/kill001/kill001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/kill/kill001/kill001a.java index 37102111a93..a9adab65dd8 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/kill/kill001/kill001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/kill/kill001/kill001a.java @@ -27,6 +27,7 @@ import nsk.share.jpda.*; import nsk.share.jdb.*; import nsk.share.jdi.JDIThreadFactory; +import jdk.test.lib.thread.VThreadPinner; import java.io.*; import java.util.*; @@ -152,6 +153,17 @@ void methodForException() { } public void run() { + boolean vthreadMode = "Virtual".equals(System.getProperty("test.thread.factory")); + if (vthreadMode) { + // JVMTI StopThread is only supported for mounted virtual threads. We need to + // pin the virtual threads so they remain mounted. + VThreadPinner.runPinned(() -> test()); + } else { + test(); + } + } + + public void test() { // Concatenate strings in advance to avoid lambda calculations later String ThreadFinished = "Thread finished: " + this.name; String CaughtExpected = "Thread " + this.name + " caught expected async exception: " + expectedException; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/jdb/Launcher.java b/test/hotspot/jtreg/vmTestbase/nsk/share/jdb/Launcher.java index d4437413495..44e476d0be7 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/share/jdb/Launcher.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdb/Launcher.java @@ -137,6 +137,9 @@ private String[] makeJdbCmdLine (String classToExecute) { /* Some tests need more carrier threads than the default provided. */ args.add("-R-Djdk.virtualThreadScheduler.parallelism=15"); } + /* Some jdb tests need java.library.path setup for native libraries. */ + String libpath = System.getProperty("java.library.path"); + args.add("-R-Djava.library.path=" + libpath); } args.addAll(argumentHandler.enwrapJavaOptions(argumentHandler.getJavaOptions())); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/stress/strace/strace007.java b/test/hotspot/jtreg/vmTestbase/nsk/stress/strace/strace007.java index 61fbc146b60..e4115432c64 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/stress/strace/strace007.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/stress/strace/strace007.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -125,6 +125,11 @@ static boolean makeSnapshot() { StackTraceElement[] all; for (int i = 1; i < THRD_COUNT; i++) { all = traces.get(threads[i]); + if (all == null) { + complain("No stacktrace for thread " + threads[i].getName() + + " was found in the set of all traces"); + return false; + } int k = all.length; if (count - k > 2) { complain("wrong lengths of stack traces:\n\t" diff --git a/test/hotspot/jtreg/vmTestbase/nsk/stress/strace/strace008.java b/test/hotspot/jtreg/vmTestbase/nsk/stress/strace/strace008.java index 24b421ae99d..f237daaf049 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/stress/strace/strace008.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/stress/strace/strace008.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -129,6 +129,11 @@ static boolean makeSnapshot() { StackTraceElement[] all; for (int i = 1; i < THRD_COUNT; i++) { all = traces.get(threads[i]); + if (all == null) { + complain("No stacktrace for thread " + threads[i].getName() + + " was found in the set of all traces"); + return false; + } int k = all.length; if (count - k > 4) { complain("wrong lengths of stack traces:\n\t" diff --git a/test/hotspot/jtreg/vmTestbase/nsk/stress/strace/strace009.java b/test/hotspot/jtreg/vmTestbase/nsk/stress/strace/strace009.java index 0f8ee03f700..ad9f77f0c58 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/stress/strace/strace009.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/stress/strace/strace009.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -129,6 +129,11 @@ static boolean makeSnapshot() { StackTraceElement[] all; for (int i = 1; i < THRD_COUNT; i++) { all = traces.get(threads[i]); + if (all == null) { + complain("No stacktrace for thread " + threads[i].getName() + + " was found in the set of all traces"); + return false; + } int k = all.length; if (count - k > 2) { complain("wrong lengths of stack traces:\n\t" diff --git a/test/hotspot/jtreg/vmTestbase/nsk/stress/strace/strace010.java b/test/hotspot/jtreg/vmTestbase/nsk/stress/strace/strace010.java index 3595ae3735f..ee07292ed01 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/stress/strace/strace010.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/stress/strace/strace010.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -145,6 +145,11 @@ boolean makeSnapshot() { StackTraceElement[] all; for (int i = 1; i < THRD_COUNT; i++) { all = traces.get(threads[i]); + if (all == null) { + complain("No stacktrace for thread " + threads[i].getName() + + " was found in the set of all traces"); + return false; + } int k = all.length; if (count - k > 2) { complain("wrong lengths of stack traces:\n\t" diff --git a/test/hotspot/jtreg/vmTestbase/nsk/stress/strace/strace011.java b/test/hotspot/jtreg/vmTestbase/nsk/stress/strace/strace011.java index eb48601b2a2..185bcbc316b 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/stress/strace/strace011.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/stress/strace/strace011.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -149,6 +149,11 @@ boolean makeSnapshot() { StackTraceElement[] all; for (int i = 1; i < THRD_COUNT; i++) { all = traces.get(threads[i]); + if (all == null) { + complain("No stacktrace for thread " + threads[i].getName() + + " was found in the set of all traces"); + return false; + } int k = all.length; if (count - k > 2) { complain("wrong lengths of stack traces:\n\t" diff --git a/test/hotspot/jtreg/vmTestbase/nsk/stress/strace/strace012.java b/test/hotspot/jtreg/vmTestbase/nsk/stress/strace/strace012.java index 4ebc3de7395..89451c97732 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/stress/strace/strace012.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/stress/strace/strace012.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -151,6 +151,11 @@ boolean makeSnapshot() { StackTraceElement[] all; for (int i = 1; i < THRD_COUNT; i++) { all = traces.get(threads[i]); + if (all == null) { + complain("No stacktrace for thread " + threads[i].getName() + + " was found in the set of all traces"); + return false; + } int k = all.length; if (count - k > 2) { complain("wrong lengths of stack traces:\n\t" diff --git a/test/hotspot/jtreg/vmTestbase/nsk/stress/strace/strace013.java b/test/hotspot/jtreg/vmTestbase/nsk/stress/strace/strace013.java index 87de7d112f8..6bff7354393 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/stress/strace/strace013.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/stress/strace/strace013.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -130,6 +130,11 @@ boolean makeSnapshot() { StackTraceElement[] all; for (int i = 1; i < THRD_COUNT; i++) { all = traces.get(threads[i]); + if (all == null) { + complain("No stacktrace for thread " + threads[i].getName() + + " was found in the set of all traces"); + return false; + } int k = all.length; if (count - k > 3) { complain("wrong lengths of stack traces:\n\t" diff --git a/test/hotspot/jtreg/vmTestbase/nsk/stress/strace/strace014.java b/test/hotspot/jtreg/vmTestbase/nsk/stress/strace/strace014.java index bc760f1722a..0ef900b35df 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/stress/strace/strace014.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/stress/strace/strace014.java @@ -140,6 +140,11 @@ boolean makeSnapshot() { StackTraceElement[] all; for (int i = 1; i < THRD_COUNT; i++) { all = traces.get(threads[i]); + if (all == null) { + complain("No stacktrace for thread " + threads[i].getName() + + " was found in the set of all traces"); + return false; + } int k = all.length; if (count - k > 4) { complain("wrong lengths of stack traces:\n\t" diff --git a/test/hotspot/jtreg/vmTestbase/nsk/stress/strace/strace015.java b/test/hotspot/jtreg/vmTestbase/nsk/stress/strace/strace015.java index 437e4f9e21c..940628cff09 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/stress/strace/strace015.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/stress/strace/strace015.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -138,6 +138,11 @@ boolean makeSnapshot() { StackTraceElement[] all; for (int i = 1; i < THRD_COUNT; i++) { all = traces.get(threads[i]); + if (all == null) { + complain("No stacktrace for thread " + threads[i].getName() + + " was found in the set of all traces"); + return false; + } int k = all.length; if (count - k > 3) { complain("wrong lengths of stack traces:\n\t" diff --git a/test/jdk/ProblemList-Virtual.txt b/test/jdk/ProblemList-Virtual.txt index eabac31ca34..d7692b578cd 100644 --- a/test/jdk/ProblemList-Virtual.txt +++ b/test/jdk/ProblemList-Virtual.txt @@ -44,8 +44,6 @@ javax/management/remote/mandatory/connection/DeadLockTest.java 8309069 windows-x javax/management/remote/mandatory/connection/ConnectionTest.java 8308352 windows-x64 -java/util/concurrent/locks/StampedLock/OOMEInStampedLock.java 8345266 generic-all - ########## ## Tests incompatible with virtual test thread factory. ## There is no goal to run all test with virtual test thread factory. diff --git a/test/jdk/com/sun/crypto/provider/KDF/HKDFDelayedPRK.java b/test/jdk/com/sun/crypto/provider/KDF/HKDFDelayedPRK.java new file mode 100644 index 00000000000..50157723416 --- /dev/null +++ b/test/jdk/com/sun/crypto/provider/KDF/HKDFDelayedPRK.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8347289 + * @summary make sure DPS works when non-extractable PRK is provided + * @library /test/lib /test/jdk/security/unsignedjce + * @build java.base/javax.crypto.ProviderVerifier + * @enablePreview + * @run main/othervm HKDFDelayedPRK + */ + +import jdk.test.lib.Asserts; + +import javax.crypto.KDF; +import javax.crypto.KDFParameters; +import javax.crypto.KDFSpi; +import javax.crypto.SecretKey; +import javax.crypto.spec.HKDFParameterSpec; +import javax.crypto.spec.SecretKeySpec; +import java.security.InvalidAlgorithmParameterException; +import java.security.Provider; +import java.security.Security; +import java.security.spec.AlgorithmParameterSpec; + +public class HKDFDelayedPRK { + public static void main(String[] args) throws Exception { + // This is a fake non-extractable key + var prk = new SecretKey() { + @Override + public String getAlgorithm() { + return "PRK"; + } + + @Override + public String getFormat() { + return null; + } + + @Override + public byte[] getEncoded() { + return null; + } + }; + + Security.addProvider(new ProviderImpl()); + var kdf = KDF.getInstance("HKDF-SHA256"); + kdf.deriveData(HKDFParameterSpec.expandOnly(prk, null, 32)); + + // Confirms our own omnipotent impl is selected + Asserts.assertEquals("P", kdf.getProviderName()); + } + + public static class ProviderImpl extends Provider { + public ProviderImpl() { + super("P", "1", "info"); + put("KDF.HKDF-SHA256", KDFImpl.class.getName()); + } + } + + // This HKDF impl accepts everything + public static class KDFImpl extends KDFSpi { + + public KDFImpl(KDFParameters params) throws InvalidAlgorithmParameterException { + super(params); + } + + @Override + protected KDFParameters engineGetParameters() { + return null; + } + + @Override + protected SecretKey engineDeriveKey(String alg, AlgorithmParameterSpec dummy) { + return new SecretKeySpec(new byte[32], alg); + } + + @Override + protected byte[] engineDeriveData(AlgorithmParameterSpec dummy) { + return new byte[32]; + } + } +} diff --git a/test/jdk/java/lang/String/concat/HiddenClassUnloading.java b/test/jdk/java/lang/String/concat/HiddenClassUnloading.java index fef6455a05f..8505ae2522b 100644 --- a/test/jdk/java/lang/String/concat/HiddenClassUnloading.java +++ b/test/jdk/java/lang/String/concat/HiddenClassUnloading.java @@ -26,13 +26,20 @@ import java.lang.invoke.*; import java.lang.management.ManagementFactory; +import jdk.test.whitebox.WhiteBox; + /** * @test * @summary Test whether the hidden class unloading of StringConcatFactory works * + * @library /test/lib + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox * @requires vm.flagless - * @run main/othervm -Xmx8M -Xms8M -Xverify:all HiddenClassUnloading - * @run main/othervm -Xmx8M -Xms8M -Xverify:all -XX:-CompactStrings HiddenClassUnloading + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. + * -Xverify:all HiddenClassUnloading + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. + * -Xverify:all -XX:-CompactStrings HiddenClassUnloading */ public class HiddenClassUnloading { public static void main(String[] args) throws Throwable { @@ -43,7 +50,7 @@ public static void main(String[] args) throws Throwable { long initUnloadedClassCount = ManagementFactory.getClassLoadingMXBean().getUnloadedClassCount(); - for (int i = 0; i < 12000; i++) { + for (int i = 0; i < 2000; i++) { int radix = types.length; String str = Integer.toString(i, radix); int length = str.length(); @@ -61,6 +68,9 @@ public static void main(String[] args) throws Throwable { ); } + // Request GC which performs class unloading + WhiteBox.getWhiteBox().fullGC(); + long unloadedClassCount = ManagementFactory.getClassLoadingMXBean().getUnloadedClassCount(); if (initUnloadedClassCount == unloadedClassCount) { throw new RuntimeException("unloadedClassCount is zero"); diff --git a/test/jdk/java/lang/Thread/virtual/MonitorEnterWaitOOME.java b/test/jdk/java/lang/Thread/virtual/MonitorEnterWaitOOME.java new file mode 100644 index 00000000000..4978e2a4b69 --- /dev/null +++ b/test/jdk/java/lang/Thread/virtual/MonitorEnterWaitOOME.java @@ -0,0 +1,148 @@ +/* + * 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 id=monitorenter + * @bug 8345266 + * @summary Test OOM while trying to unmount vthread on monitorenter + * @requires vm.continuations & vm.gc.G1 & vm.opt.DisableExplicitGC != "true" + * @library /test/lib + * @run main/othervm -XX:+UseG1GC -Xmx48M MonitorEnterWaitOOME false + */ + +/* + * @test id=timedwait + * @summary Test OOM while trying to unmount vthread on Object.wait + * @requires vm.continuations & vm.gc.G1 & vm.opt.DisableExplicitGC != "true" + * @library /test/lib + * @run main/othervm -XX:+UseG1GC -Xmx48M MonitorEnterWaitOOME true 5 + */ + +/* + * @test id=untimedwait + * @summary Test OOM while trying to unmount vthread on Object.wait + * @requires vm.continuations & vm.gc.G1 & vm.opt.DisableExplicitGC != "true" + * @library /test/lib + * @run main/othervm -XX:+UseG1GC -Xmx48M MonitorEnterWaitOOME true 0 + */ + +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; + +import jdk.test.lib.thread.VThreadRunner; + +public class MonitorEnterWaitOOME { + static volatile Object data; + static Thread.State dummyState = Thread.State.RUNNABLE; // load java.lang.Thread$State + + public static void main(String[] args) throws Throwable { + final boolean testWait = args.length >= 1 ? Boolean.parseBoolean(args[0]) : false; + final long timeout = testWait && args.length == 2 ? Long.parseLong(args[1]) : 0L; + + VThreadRunner.ensureParallelism(2); + + Thread vthread; + var lock = new Object(); + var canFillHeap = new AtomicBoolean(); + var heapFilled = new AtomicBoolean(); + var heapCollected = new AtomicBoolean(); + var exRef = new AtomicReference<Throwable>(); + synchronized (lock) { + vthread = Thread.ofVirtual().start(() -> { + try { + awaitTrue(canFillHeap); + data = fillHeap(); + heapFilled.set(true); + synchronized (lock) { + if (testWait) { + lock.wait(timeout); + } + } + data = null; + System.gc(); + heapCollected.set(true); + } catch (Throwable e) { + data = null; + System.gc(); // avoid nested OOME + exRef.set(e); + } + }); + canFillHeap.set(true); + awaitTrue(heapFilled); + awaitState(vthread, Thread.State.BLOCKED); + } + if (testWait && timeout == 0) { + awaitState(vthread, Thread.State.WAITING); + synchronized (lock) { + lock.notify(); + } + } + joinVThread(vthread, heapCollected, exRef); + assert exRef.get() == null; + } + + private static Object[] fillHeap() { + Object[] first = null, last = null; + int size = 1 << 20; + while (size > 0) { + try { + Object[] array = new Object[size]; + if (first == null) { + first = array; + } else { + last[0] = array; + } + last = array; + } catch (OutOfMemoryError oome) { + size = size >>> 1; + } + } + return first; + } + + private static void awaitTrue(AtomicBoolean ready) { + // Don't call anything that might allocate from the Java heap. + while (!ready.get()) { + Thread.onSpinWait(); + } + } + + private static void awaitState(Thread thread, Thread.State expectedState) { + // Don't call anything that might allocate from the Java heap. + while (thread.getState() != expectedState) { + Thread.onSpinWait(); + } + } + + private static void joinVThread(Thread vthread, AtomicBoolean ready, AtomicReference<Throwable> exRef) throws Throwable { + // Don't call anything that might allocate from the Java heap until ready is set. + while (!ready.get()) { + Throwable ex = exRef.get(); + if (ex != null) { + throw ex; + } + Thread.onSpinWait(); + } + vthread.join(); + } +} diff --git a/test/jdk/java/net/Socket/ConnectFailTest.java b/test/jdk/java/net/Socket/ConnectFailTest.java index 7cc46ce4a4d..f21ed7d132d 100644 --- a/test/jdk/java/net/Socket/ConnectFailTest.java +++ b/test/jdk/java/net/Socket/ConnectFailTest.java @@ -29,6 +29,7 @@ import java.io.IOException; import java.net.InetAddress; import java.net.InetSocketAddress; +import java.net.Proxy; import java.net.ServerSocket; import java.net.Socket; import java.net.SocketException; @@ -36,6 +37,7 @@ import java.nio.channels.SocketChannel; import java.util.List; +import static java.net.InetAddress.getLoopbackAddress; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -50,6 +52,8 @@ */ class ConnectFailTest { + // Implementation Note: Explicitly binding on the loopback address to avoid potential unstabilities. + private static final int DEAD_SERVER_PORT = 0xDEAD; private static final InetSocketAddress REFUSING_SOCKET_ADDRESS = Utils.refusingEndpoint(); @@ -83,7 +87,7 @@ void testUnboundSocket(Socket socket) throws IOException { @MethodSource("sockets") void testBoundSocket(Socket socket) throws IOException { try (socket) { - socket.bind(new InetSocketAddress(0)); + socket.bind(new InetSocketAddress(getLoopbackAddress(), 0)); assertTrue(socket.isBound()); assertFalse(socket.isConnected()); assertThrows(IOException.class, () -> socket.connect(REFUSING_SOCKET_ADDRESS)); @@ -132,7 +136,7 @@ void testUnboundSocketWithUnresolvedAddress(Socket socket) throws IOException { @MethodSource("sockets") void testBoundSocketWithUnresolvedAddress(Socket socket) throws IOException { try (socket) { - socket.bind(new InetSocketAddress(0)); + socket.bind(new InetSocketAddress(getLoopbackAddress(), 0)); assertTrue(socket.isBound()); assertFalse(socket.isConnected()); assertThrows(UnknownHostException.class, () -> socket.connect(UNRESOLVED_ADDRESS)); @@ -161,7 +165,8 @@ static List<Socket> sockets() throws Exception { Socket socket = new Socket(); @SuppressWarnings("resource") Socket channelSocket = SocketChannel.open().socket(); - return List.of(socket, channelSocket); + Socket noProxySocket = new Socket(Proxy.NO_PROXY); + return List.of(socket, channelSocket, noProxySocket); } private static ServerSocket createEphemeralServerSocket() throws IOException { diff --git a/test/jdk/java/net/Socket/ConnectSocksProxyTest.java b/test/jdk/java/net/Socket/ConnectSocksProxyTest.java new file mode 100644 index 00000000000..8bea5ff816e --- /dev/null +++ b/test/jdk/java/net/Socket/ConnectSocksProxyTest.java @@ -0,0 +1,218 @@ +/* + * 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 jdk.test.lib.Utils; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.net.Authenticator; +import java.net.InetSocketAddress; +import java.net.PasswordAuthentication; +import java.net.Proxy; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.SocketException; + +import static java.net.InetAddress.getLoopbackAddress; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/* + * @test + * @bug 8346017 + * @summary Verifies the `connect()` behaviour of a SOCKS proxy socket. In particular, that passing a resolvable + * unresolved address doesn't throw an exception. + * @library /test/lib /java/net/Socks + * @build SocksServer + * @run junit ConnectSocksProxyTest + */ +class ConnectSocksProxyTest { + + // Implementation Note: Explicitly binding on the loopback address to avoid potential unstabilities. + + private static final int DEAD_SERVER_PORT = 0xDEAD; + + private static final InetSocketAddress REFUSING_SOCKET_ADDRESS = Utils.refusingEndpoint(); + + private static final InetSocketAddress UNRESOLVED_ADDRESS = + InetSocketAddress.createUnresolved("no.such.host", DEAD_SERVER_PORT); + + private static final String PROXY_AUTH_USERNAME = "foo"; + + private static final String PROXY_AUTH_PASSWORD = "bar"; + + private static SocksServer PROXY_SERVER; + + private static Proxy PROXY; + + @BeforeAll + static void initAuthenticator() { + Authenticator.setDefault(new Authenticator() { + @Override + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication(PROXY_AUTH_USERNAME, PROXY_AUTH_PASSWORD.toCharArray()); + } + }); + } + + @BeforeAll + static void initProxyServer() throws IOException { + PROXY_SERVER = new SocksServer(getLoopbackAddress(), 0, false); + PROXY_SERVER.addUser(PROXY_AUTH_USERNAME, PROXY_AUTH_PASSWORD); + PROXY_SERVER.start(); + InetSocketAddress proxyAddress = new InetSocketAddress(getLoopbackAddress(), PROXY_SERVER.getPort()); + PROXY = new Proxy(Proxy.Type.SOCKS, proxyAddress); + } + + @AfterAll + static void stopProxyServer() { + PROXY_SERVER.close(); + } + + @Test + void testUnresolvedAddress() { + assertTrue(UNRESOLVED_ADDRESS.isUnresolved()); + } + + /** + * Verifies that an unbound socket is closed when {@code connect()} fails. + */ + @Test + void testUnboundSocket() throws IOException { + try (Socket socket = createProxiedSocket()) { + assertFalse(socket.isBound()); + assertFalse(socket.isConnected()); + assertThrows(IOException.class, () -> socket.connect(REFUSING_SOCKET_ADDRESS)); + assertTrue(socket.isClosed()); + } + } + + /** + * Verifies that a bound socket is closed when {@code connect()} fails. + */ + @Test + void testBoundSocket() throws IOException { + try (Socket socket = createProxiedSocket()) { + socket.bind(new InetSocketAddress(getLoopbackAddress(), 0)); + assertTrue(socket.isBound()); + assertFalse(socket.isConnected()); + assertThrows(IOException.class, () -> socket.connect(REFUSING_SOCKET_ADDRESS)); + assertTrue(socket.isClosed()); + } + } + + /** + * Verifies that a connected socket is not closed when {@code connect()} fails. + */ + @Test + void testConnectedSocket() throws Throwable { + try (Socket socket = createProxiedSocket(); + ServerSocket serverSocket = createEphemeralServerSocket()) { + socket.connect(serverSocket.getLocalSocketAddress()); + try (Socket _ = serverSocket.accept()) { + assertTrue(socket.isBound()); + assertTrue(socket.isConnected()); + SocketException exception = assertThrows( + SocketException.class, + () -> socket.connect(REFUSING_SOCKET_ADDRESS)); + assertEquals("Already connected", exception.getMessage()); + assertFalse(socket.isClosed()); + } + } + } + + /** + * Delegates to {@link #testUnconnectedSocketWithUnresolvedAddress(boolean, Socket)} using an unbound socket. + */ + @Test + void testUnboundSocketWithUnresolvedAddress() throws IOException { + try (Socket socket = createProxiedSocket()) { + assertFalse(socket.isBound()); + assertFalse(socket.isConnected()); + testUnconnectedSocketWithUnresolvedAddress(false, socket); + } + } + + /** + * Delegates to {@link #testUnconnectedSocketWithUnresolvedAddress(boolean, Socket)} using a bound socket. + */ + @Test + void testBoundSocketWithUnresolvedAddress() throws IOException { + try (Socket socket = createProxiedSocket()) { + socket.bind(new InetSocketAddress(getLoopbackAddress(), 0)); + testUnconnectedSocketWithUnresolvedAddress(true, socket); + } + } + + /** + * Verifies the behaviour of an unconnected socket when {@code connect()} is invoked using an unresolved address. + */ + private static void testUnconnectedSocketWithUnresolvedAddress(boolean bound, Socket socket) throws IOException { + assertEquals(bound, socket.isBound()); + assertFalse(socket.isConnected()); + try (ServerSocket serverSocket = createEphemeralServerSocket()) { + InetSocketAddress unresolvedAddress = InetSocketAddress.createUnresolved( + getLoopbackAddress().getHostAddress(), + serverSocket.getLocalPort()); + socket.connect(unresolvedAddress); + try (Socket _ = serverSocket.accept()) { + assertTrue(socket.isBound()); + assertTrue(socket.isConnected()); + assertFalse(socket.isClosed()); + } + } + } + + /** + * Verifies that a connected socket is not closed when {@code connect()} is invoked using an unresolved address. + */ + @Test + void testConnectedSocketWithUnresolvedAddress() throws Throwable { + try (Socket socket = createProxiedSocket(); + ServerSocket serverSocket = createEphemeralServerSocket()) { + socket.connect(serverSocket.getLocalSocketAddress()); + try (Socket _ = serverSocket.accept()) { + assertTrue(socket.isBound()); + assertTrue(socket.isConnected()); + SocketException exception = assertThrows( + SocketException.class, + () -> socket.connect(UNRESOLVED_ADDRESS)); + assertEquals("Already connected", exception.getMessage()); + assertFalse(socket.isClosed()); + } + } + } + + private static Socket createProxiedSocket() { + return new Socket(PROXY); + } + + private static ServerSocket createEphemeralServerSocket() throws IOException { + return new ServerSocket(0, 0, getLoopbackAddress()); + } + +} diff --git a/test/jdk/java/util/stream/GatherersMapConcurrentTest.java b/test/jdk/java/util/stream/GatherersMapConcurrentTest.java index f7cc1c42a3c..970a550400a 100644 --- a/test/jdk/java/util/stream/GatherersMapConcurrentTest.java +++ b/test/jdk/java/util/stream/GatherersMapConcurrentTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +24,9 @@ import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Semaphore; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.locks.LockSupport; +import java.util.function.Function; import java.util.stream.Gatherer; import java.util.stream.Gatherers; import java.util.stream.Stream; @@ -298,7 +301,7 @@ public void behavesAsExpected(ConcurrencyConfig cc) { @ParameterizedTest @MethodSource("concurrencyConfigurations") - public void behavesAsExpectedWhenShortCircuited(ConcurrencyConfig cc) { + public void shortCircuits(ConcurrencyConfig cc) { final var limitTo = Math.max(cc.config().streamSize() / 2, 1); final var expectedResult = cc.config().stream() @@ -313,4 +316,60 @@ public void behavesAsExpectedWhenShortCircuited(ConcurrencyConfig cc) { assertEquals(expectedResult, result); } + + @ParameterizedTest + @MethodSource("concurrencyConfigurations") + public void ignoresAndRestoresCallingThreadInterruption(ConcurrencyConfig cc) { + final var limitTo = Math.max(cc.config().streamSize() / 2, 1); + + final var expectedResult = cc.config().stream() + .map(x -> x * x) + .limit(limitTo) + .toList(); + + // Ensure calling thread is interrupted + Thread.currentThread().interrupt(); + + final var result = cc.config().stream() + .gather(Gatherers.mapConcurrent(cc.concurrencyLevel(), x -> { + LockSupport.parkNanos(10000); // 10 us + return x * x; + })) + .limit(limitTo) + .toList(); + + // Ensure calling thread remains interrupted + assertEquals(true, Thread.interrupted()); + + assertEquals(expectedResult, result); + } + + @ParameterizedTest + @MethodSource("concurrencyConfigurations") + public void limitsWorkInProgressToMaxConcurrency(ConcurrencyConfig cc) { + final var elementNum = new AtomicLong(0); + final var wipCount = new AtomicLong(0); + final var limitTo = Math.max(cc.config().streamSize() / 2, 1); + + final var expectedResult = cc.config().stream() + .map(x -> x * x) + .limit(limitTo) + .toList(); + + Function<Integer, Integer> fun = x -> { + if (wipCount.incrementAndGet() > cc.concurrencyLevel) + throw new IllegalStateException("Too much wip!"); + if (elementNum.getAndIncrement() == 0) + LockSupport.parkNanos(500_000_000); // 500 ms + return x * x; + }; + + final var result = cc.config().stream() + .gather(Gatherers.mapConcurrent(cc.concurrencyLevel(), fun)) + .gather(Gatherer.of((v, e, d) -> wipCount.decrementAndGet() >= 0 && d.push(e))) + .limit(limitTo) + .toList(); + + assertEquals(expectedResult, result); + } } diff --git a/test/jdk/javax/accessibility/TestJMenuItemShortcutAccessibility.java b/test/jdk/javax/accessibility/TestJMenuItemShortcutAccessibility.java new file mode 100644 index 00000000000..acd7ec3c64a --- /dev/null +++ b/test/jdk/javax/accessibility/TestJMenuItemShortcutAccessibility.java @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import javax.swing.JFrame; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.KeyStroke; + +/* + * @test + * @bug 8339728 + * @summary Tests that JAWS announce the shortcuts for JMenuItems. + * @requires os.family == "windows" + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual TestJMenuItemShortcutAccessibility + */ + +public class TestJMenuItemShortcutAccessibility { + public static void main(String[] args) throws Exception { + String INSTRUCTIONS = """ + 1. Start the JAWS application + 2. Press Alt + M to open application Menu + 3. Navigate the Menu Items by using UP / DOWN arrow key + 4. Press Pass if you are able to hear correct JAWS announcements + (JAWS should read full shortcut text and not only the 1st + character of shortcut text for each menu item) else Fail + """; + + PassFailJFrame.builder() + .title("TestJMenuItemShortcutAccessibility Instruction") + .instructions(INSTRUCTIONS) + .columns(35) + .testUI(TestJMenuItemShortcutAccessibility::createUI) + .build() + .awaitAndCheck(); + } + + private static JFrame createUI() { + JFrame frame = new JFrame("A Frame with Menu"); + + JMenuBar menuBar = new JMenuBar(); + JMenu menu = new JMenu("Menu with shortcuts"); + menu.setMnemonic(KeyEvent.VK_M); + menuBar.add(menu); + + KeyStroke keyStroke1 = KeyStroke.getKeyStroke(KeyEvent.VK_F, + InputEvent.CTRL_DOWN_MASK); + KeyStroke keyStroke2 = KeyStroke.getKeyStroke(KeyEvent.VK_2, + InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK); + KeyStroke keyStroke3 = KeyStroke.getKeyStroke(KeyEvent.VK_F1, + InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK); + KeyStroke keyStroke4 = KeyStroke.getKeyStroke(KeyEvent.VK_COMMA, + InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK); + KeyStroke keyStroke5 = KeyStroke.getKeyStroke(KeyEvent.VK_PERIOD, + InputEvent.CTRL_DOWN_MASK | InputEvent.ALT_DOWN_MASK); + KeyStroke keyStroke6 = KeyStroke.getKeyStroke(KeyEvent.VK_TAB, + InputEvent.CTRL_DOWN_MASK); + KeyStroke keyStroke7 = KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, + InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK); + + JMenuItem menuItem1 = new JMenuItem("First Menu Item"); + menuItem1.setAccelerator(keyStroke1); + JMenuItem menuItem2 = new JMenuItem("Second Menu Item"); + menuItem2.setAccelerator(keyStroke2); + JMenuItem menuItem3 = new JMenuItem("Third Menu Item"); + menuItem3.setAccelerator(keyStroke3); + JMenuItem menuItem4 = new JMenuItem("Fourth Menu Item"); + menuItem4.setAccelerator(keyStroke4); + JMenuItem menuItem5 = new JMenuItem("Fifth Menu Item"); + menuItem5.setAccelerator(keyStroke5); + JMenuItem menuItem6 = new JMenuItem("Sixth Menu Item"); + menuItem6.setAccelerator(keyStroke6); + JMenuItem menuItem7 = new JMenuItem("Seventh Menu Item"); + menuItem7.setAccelerator(keyStroke7); + + menu.add(menuItem1); + menu.add(menuItem2); + menu.add(menuItem3); + menu.add(menuItem4); + menu.add(menuItem5); + menu.add(menuItem6); + menu.add(menuItem7); + + frame.setJMenuBar(menuBar); + frame.setSize(300, 200); + return frame; + } +} diff --git a/test/jdk/jdk/classfile/ClassPrinterTest.java b/test/jdk/jdk/classfile/ClassPrinterTest.java index 5dc136f59c3..506f3382b83 100644 --- a/test/jdk/jdk/classfile/ClassPrinterTest.java +++ b/test/jdk/jdk/classfile/ClassPrinterTest.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8335927 + * @bug 8335927 8345773 * @summary Testing ClassFile ClassPrinter. * @run junit ClassPrinterTest */ @@ -122,8 +122,7 @@ ClassModel getClassModel() { @Test void testPrintYamlTraceAll() throws IOException { - var out = new StringBuilder(); - ClassPrinter.toYaml(getClassModel(), ClassPrinter.Verbosity.TRACE_ALL, out::append); + var out = getClassModel().toDebugString(); assertOut(out, """ - class name: Foo @@ -904,7 +903,7 @@ void testWalkMembersOnly() throws IOException { assertEquals(node.walk().count(), 42); } - private static void assertOut(StringBuilder out, String expected) { + private static void assertOut(CharSequence out, String expected) { // System.out.println("-----------------"); // System.out.println(out.toString()); // System.out.println("-----------------"); diff --git a/test/jdk/jdk/classfile/SnippetsTest.java b/test/jdk/jdk/classfile/SnippetsTest.java index f6fa2281e14..2b84820e9b9 100644 --- a/test/jdk/jdk/classfile/SnippetsTest.java +++ b/test/jdk/jdk/classfile/SnippetsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,7 +42,9 @@ public class SnippetsTest { @ParameterizedTest @ValueSource(strings = { "src/java.base/share/classes/java/lang/classfile/snippet-files/PackageSnippets.java", - "src/java.base/share/classes/jdk/internal/classfile/components/snippet-files/PackageSnippets.java"}) + "src/java.base/share/classes/java/lang/classfile/constantpool/snippet-files/PackageSnippets.java", + "src/java.base/share/classes/jdk/internal/classfile/components/snippet-files/PackageSnippets.java" + }) void testSnippet(String source) throws Exception { var p = Paths.get(System.getProperty("test.src", ".")).toAbsolutePath(); while ((p = p.getParent()) != null) { diff --git a/test/jdk/jdk/incubator/vector/Byte128VectorTests.java b/test/jdk/jdk/incubator/vector/Byte128VectorTests.java index 36a140c474a..7c8265169f4 100644 --- a/test/jdk/jdk/incubator/vector/Byte128VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Byte128VectorTests.java @@ -3912,6 +3912,184 @@ static void MAXReduceByte128VectorTestsMasked(IntFunction<byte[]> fa, IntFunctio Byte128VectorTests::MAXReduceMasked, Byte128VectorTests::MAXReduceAllMasked); } + static byte UMINReduce(byte[] a, int idx) { + byte res = Byte.MAX_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = (byte) VectorMath.minUnsigned(res, a[i]); + } + + return res; + } + + static byte UMINReduceAll(byte[] a) { + byte res = Byte.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (byte) VectorMath.minUnsigned(res, UMINReduce(a, i)); + } + + return res; + } + + @Test(dataProvider = "byteUnaryOpProvider") + static void UMINReduceByte128VectorTests(IntFunction<byte[]> fa) { + byte[] a = fa.apply(SPECIES.length()); + byte[] r = fr.apply(SPECIES.length()); + byte ra = Byte.MAX_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMIN); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Byte.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + ra = (byte) VectorMath.minUnsigned(ra, av.reduceLanes(VectorOperators.UMIN)); + } + } + + assertReductionArraysEquals(r, ra, a, + Byte128VectorTests::UMINReduce, Byte128VectorTests::UMINReduceAll); + } + + static byte UMINReduceMasked(byte[] a, int idx, boolean[] mask) { + byte res = Byte.MAX_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = (byte) VectorMath.minUnsigned(res, a[i]); + } + + return res; + } + + static byte UMINReduceAllMasked(byte[] a, boolean[] mask) { + byte res = Byte.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (byte) VectorMath.minUnsigned(res, UMINReduceMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "byteUnaryOpMaskProvider") + static void UMINReduceByte128VectorTestsMasked(IntFunction<byte[]> fa, IntFunction<boolean[]> fm) { + byte[] a = fa.apply(SPECIES.length()); + byte[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask<Byte> vmask = VectorMask.fromArray(SPECIES, mask, 0); + byte ra = Byte.MAX_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMIN, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Byte.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + ra = (byte) VectorMath.minUnsigned(ra, av.reduceLanes(VectorOperators.UMIN, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Byte128VectorTests::UMINReduceMasked, Byte128VectorTests::UMINReduceAllMasked); + } + + static byte UMAXReduce(byte[] a, int idx) { + byte res = Byte.MIN_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = (byte) VectorMath.maxUnsigned(res, a[i]); + } + + return res; + } + + static byte UMAXReduceAll(byte[] a) { + byte res = Byte.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (byte) VectorMath.maxUnsigned(res, UMAXReduce(a, i)); + } + + return res; + } + + @Test(dataProvider = "byteUnaryOpProvider") + static void UMAXReduceByte128VectorTests(IntFunction<byte[]> fa) { + byte[] a = fa.apply(SPECIES.length()); + byte[] r = fr.apply(SPECIES.length()); + byte ra = Byte.MIN_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMAX); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Byte.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + ra = (byte) VectorMath.maxUnsigned(ra, av.reduceLanes(VectorOperators.UMAX)); + } + } + + assertReductionArraysEquals(r, ra, a, + Byte128VectorTests::UMAXReduce, Byte128VectorTests::UMAXReduceAll); + } + + static byte UMAXReduceMasked(byte[] a, int idx, boolean[] mask) { + byte res = Byte.MIN_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = (byte) VectorMath.maxUnsigned(res, a[i]); + } + + return res; + } + + static byte UMAXReduceAllMasked(byte[] a, boolean[] mask) { + byte res = Byte.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (byte) VectorMath.maxUnsigned(res, UMAXReduceMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "byteUnaryOpMaskProvider") + static void UMAXReduceByte128VectorTestsMasked(IntFunction<byte[]> fa, IntFunction<boolean[]> fm) { + byte[] a = fa.apply(SPECIES.length()); + byte[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask<Byte> vmask = VectorMask.fromArray(SPECIES, mask, 0); + byte ra = Byte.MIN_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMAX, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Byte.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + ra = (byte) VectorMath.maxUnsigned(ra, av.reduceLanes(VectorOperators.UMAX, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Byte128VectorTests::UMAXReduceMasked, Byte128VectorTests::UMAXReduceAllMasked); + } + static byte FIRST_NONZEROReduce(byte[] a, int idx) { byte res = (byte) 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { diff --git a/test/jdk/jdk/incubator/vector/Byte256VectorTests.java b/test/jdk/jdk/incubator/vector/Byte256VectorTests.java index 0ad567b5ee4..0fbbca79f5d 100644 --- a/test/jdk/jdk/incubator/vector/Byte256VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Byte256VectorTests.java @@ -3912,6 +3912,184 @@ static void MAXReduceByte256VectorTestsMasked(IntFunction<byte[]> fa, IntFunctio Byte256VectorTests::MAXReduceMasked, Byte256VectorTests::MAXReduceAllMasked); } + static byte UMINReduce(byte[] a, int idx) { + byte res = Byte.MAX_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = (byte) VectorMath.minUnsigned(res, a[i]); + } + + return res; + } + + static byte UMINReduceAll(byte[] a) { + byte res = Byte.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (byte) VectorMath.minUnsigned(res, UMINReduce(a, i)); + } + + return res; + } + + @Test(dataProvider = "byteUnaryOpProvider") + static void UMINReduceByte256VectorTests(IntFunction<byte[]> fa) { + byte[] a = fa.apply(SPECIES.length()); + byte[] r = fr.apply(SPECIES.length()); + byte ra = Byte.MAX_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMIN); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Byte.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + ra = (byte) VectorMath.minUnsigned(ra, av.reduceLanes(VectorOperators.UMIN)); + } + } + + assertReductionArraysEquals(r, ra, a, + Byte256VectorTests::UMINReduce, Byte256VectorTests::UMINReduceAll); + } + + static byte UMINReduceMasked(byte[] a, int idx, boolean[] mask) { + byte res = Byte.MAX_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = (byte) VectorMath.minUnsigned(res, a[i]); + } + + return res; + } + + static byte UMINReduceAllMasked(byte[] a, boolean[] mask) { + byte res = Byte.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (byte) VectorMath.minUnsigned(res, UMINReduceMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "byteUnaryOpMaskProvider") + static void UMINReduceByte256VectorTestsMasked(IntFunction<byte[]> fa, IntFunction<boolean[]> fm) { + byte[] a = fa.apply(SPECIES.length()); + byte[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask<Byte> vmask = VectorMask.fromArray(SPECIES, mask, 0); + byte ra = Byte.MAX_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMIN, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Byte.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + ra = (byte) VectorMath.minUnsigned(ra, av.reduceLanes(VectorOperators.UMIN, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Byte256VectorTests::UMINReduceMasked, Byte256VectorTests::UMINReduceAllMasked); + } + + static byte UMAXReduce(byte[] a, int idx) { + byte res = Byte.MIN_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = (byte) VectorMath.maxUnsigned(res, a[i]); + } + + return res; + } + + static byte UMAXReduceAll(byte[] a) { + byte res = Byte.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (byte) VectorMath.maxUnsigned(res, UMAXReduce(a, i)); + } + + return res; + } + + @Test(dataProvider = "byteUnaryOpProvider") + static void UMAXReduceByte256VectorTests(IntFunction<byte[]> fa) { + byte[] a = fa.apply(SPECIES.length()); + byte[] r = fr.apply(SPECIES.length()); + byte ra = Byte.MIN_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMAX); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Byte.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + ra = (byte) VectorMath.maxUnsigned(ra, av.reduceLanes(VectorOperators.UMAX)); + } + } + + assertReductionArraysEquals(r, ra, a, + Byte256VectorTests::UMAXReduce, Byte256VectorTests::UMAXReduceAll); + } + + static byte UMAXReduceMasked(byte[] a, int idx, boolean[] mask) { + byte res = Byte.MIN_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = (byte) VectorMath.maxUnsigned(res, a[i]); + } + + return res; + } + + static byte UMAXReduceAllMasked(byte[] a, boolean[] mask) { + byte res = Byte.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (byte) VectorMath.maxUnsigned(res, UMAXReduceMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "byteUnaryOpMaskProvider") + static void UMAXReduceByte256VectorTestsMasked(IntFunction<byte[]> fa, IntFunction<boolean[]> fm) { + byte[] a = fa.apply(SPECIES.length()); + byte[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask<Byte> vmask = VectorMask.fromArray(SPECIES, mask, 0); + byte ra = Byte.MIN_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMAX, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Byte.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + ra = (byte) VectorMath.maxUnsigned(ra, av.reduceLanes(VectorOperators.UMAX, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Byte256VectorTests::UMAXReduceMasked, Byte256VectorTests::UMAXReduceAllMasked); + } + static byte FIRST_NONZEROReduce(byte[] a, int idx) { byte res = (byte) 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { diff --git a/test/jdk/jdk/incubator/vector/Byte512VectorTests.java b/test/jdk/jdk/incubator/vector/Byte512VectorTests.java index 0edc66dfccc..a17e621a0e6 100644 --- a/test/jdk/jdk/incubator/vector/Byte512VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Byte512VectorTests.java @@ -3912,6 +3912,184 @@ static void MAXReduceByte512VectorTestsMasked(IntFunction<byte[]> fa, IntFunctio Byte512VectorTests::MAXReduceMasked, Byte512VectorTests::MAXReduceAllMasked); } + static byte UMINReduce(byte[] a, int idx) { + byte res = Byte.MAX_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = (byte) VectorMath.minUnsigned(res, a[i]); + } + + return res; + } + + static byte UMINReduceAll(byte[] a) { + byte res = Byte.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (byte) VectorMath.minUnsigned(res, UMINReduce(a, i)); + } + + return res; + } + + @Test(dataProvider = "byteUnaryOpProvider") + static void UMINReduceByte512VectorTests(IntFunction<byte[]> fa) { + byte[] a = fa.apply(SPECIES.length()); + byte[] r = fr.apply(SPECIES.length()); + byte ra = Byte.MAX_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMIN); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Byte.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + ra = (byte) VectorMath.minUnsigned(ra, av.reduceLanes(VectorOperators.UMIN)); + } + } + + assertReductionArraysEquals(r, ra, a, + Byte512VectorTests::UMINReduce, Byte512VectorTests::UMINReduceAll); + } + + static byte UMINReduceMasked(byte[] a, int idx, boolean[] mask) { + byte res = Byte.MAX_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = (byte) VectorMath.minUnsigned(res, a[i]); + } + + return res; + } + + static byte UMINReduceAllMasked(byte[] a, boolean[] mask) { + byte res = Byte.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (byte) VectorMath.minUnsigned(res, UMINReduceMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "byteUnaryOpMaskProvider") + static void UMINReduceByte512VectorTestsMasked(IntFunction<byte[]> fa, IntFunction<boolean[]> fm) { + byte[] a = fa.apply(SPECIES.length()); + byte[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask<Byte> vmask = VectorMask.fromArray(SPECIES, mask, 0); + byte ra = Byte.MAX_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMIN, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Byte.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + ra = (byte) VectorMath.minUnsigned(ra, av.reduceLanes(VectorOperators.UMIN, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Byte512VectorTests::UMINReduceMasked, Byte512VectorTests::UMINReduceAllMasked); + } + + static byte UMAXReduce(byte[] a, int idx) { + byte res = Byte.MIN_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = (byte) VectorMath.maxUnsigned(res, a[i]); + } + + return res; + } + + static byte UMAXReduceAll(byte[] a) { + byte res = Byte.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (byte) VectorMath.maxUnsigned(res, UMAXReduce(a, i)); + } + + return res; + } + + @Test(dataProvider = "byteUnaryOpProvider") + static void UMAXReduceByte512VectorTests(IntFunction<byte[]> fa) { + byte[] a = fa.apply(SPECIES.length()); + byte[] r = fr.apply(SPECIES.length()); + byte ra = Byte.MIN_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMAX); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Byte.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + ra = (byte) VectorMath.maxUnsigned(ra, av.reduceLanes(VectorOperators.UMAX)); + } + } + + assertReductionArraysEquals(r, ra, a, + Byte512VectorTests::UMAXReduce, Byte512VectorTests::UMAXReduceAll); + } + + static byte UMAXReduceMasked(byte[] a, int idx, boolean[] mask) { + byte res = Byte.MIN_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = (byte) VectorMath.maxUnsigned(res, a[i]); + } + + return res; + } + + static byte UMAXReduceAllMasked(byte[] a, boolean[] mask) { + byte res = Byte.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (byte) VectorMath.maxUnsigned(res, UMAXReduceMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "byteUnaryOpMaskProvider") + static void UMAXReduceByte512VectorTestsMasked(IntFunction<byte[]> fa, IntFunction<boolean[]> fm) { + byte[] a = fa.apply(SPECIES.length()); + byte[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask<Byte> vmask = VectorMask.fromArray(SPECIES, mask, 0); + byte ra = Byte.MIN_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMAX, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Byte.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + ra = (byte) VectorMath.maxUnsigned(ra, av.reduceLanes(VectorOperators.UMAX, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Byte512VectorTests::UMAXReduceMasked, Byte512VectorTests::UMAXReduceAllMasked); + } + static byte FIRST_NONZEROReduce(byte[] a, int idx) { byte res = (byte) 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { diff --git a/test/jdk/jdk/incubator/vector/Byte64VectorTests.java b/test/jdk/jdk/incubator/vector/Byte64VectorTests.java index 98c8382c526..58f1d6295a0 100644 --- a/test/jdk/jdk/incubator/vector/Byte64VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Byte64VectorTests.java @@ -3912,6 +3912,184 @@ static void MAXReduceByte64VectorTestsMasked(IntFunction<byte[]> fa, IntFunction Byte64VectorTests::MAXReduceMasked, Byte64VectorTests::MAXReduceAllMasked); } + static byte UMINReduce(byte[] a, int idx) { + byte res = Byte.MAX_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = (byte) VectorMath.minUnsigned(res, a[i]); + } + + return res; + } + + static byte UMINReduceAll(byte[] a) { + byte res = Byte.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (byte) VectorMath.minUnsigned(res, UMINReduce(a, i)); + } + + return res; + } + + @Test(dataProvider = "byteUnaryOpProvider") + static void UMINReduceByte64VectorTests(IntFunction<byte[]> fa) { + byte[] a = fa.apply(SPECIES.length()); + byte[] r = fr.apply(SPECIES.length()); + byte ra = Byte.MAX_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMIN); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Byte.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + ra = (byte) VectorMath.minUnsigned(ra, av.reduceLanes(VectorOperators.UMIN)); + } + } + + assertReductionArraysEquals(r, ra, a, + Byte64VectorTests::UMINReduce, Byte64VectorTests::UMINReduceAll); + } + + static byte UMINReduceMasked(byte[] a, int idx, boolean[] mask) { + byte res = Byte.MAX_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = (byte) VectorMath.minUnsigned(res, a[i]); + } + + return res; + } + + static byte UMINReduceAllMasked(byte[] a, boolean[] mask) { + byte res = Byte.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (byte) VectorMath.minUnsigned(res, UMINReduceMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "byteUnaryOpMaskProvider") + static void UMINReduceByte64VectorTestsMasked(IntFunction<byte[]> fa, IntFunction<boolean[]> fm) { + byte[] a = fa.apply(SPECIES.length()); + byte[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask<Byte> vmask = VectorMask.fromArray(SPECIES, mask, 0); + byte ra = Byte.MAX_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMIN, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Byte.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + ra = (byte) VectorMath.minUnsigned(ra, av.reduceLanes(VectorOperators.UMIN, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Byte64VectorTests::UMINReduceMasked, Byte64VectorTests::UMINReduceAllMasked); + } + + static byte UMAXReduce(byte[] a, int idx) { + byte res = Byte.MIN_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = (byte) VectorMath.maxUnsigned(res, a[i]); + } + + return res; + } + + static byte UMAXReduceAll(byte[] a) { + byte res = Byte.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (byte) VectorMath.maxUnsigned(res, UMAXReduce(a, i)); + } + + return res; + } + + @Test(dataProvider = "byteUnaryOpProvider") + static void UMAXReduceByte64VectorTests(IntFunction<byte[]> fa) { + byte[] a = fa.apply(SPECIES.length()); + byte[] r = fr.apply(SPECIES.length()); + byte ra = Byte.MIN_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMAX); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Byte.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + ra = (byte) VectorMath.maxUnsigned(ra, av.reduceLanes(VectorOperators.UMAX)); + } + } + + assertReductionArraysEquals(r, ra, a, + Byte64VectorTests::UMAXReduce, Byte64VectorTests::UMAXReduceAll); + } + + static byte UMAXReduceMasked(byte[] a, int idx, boolean[] mask) { + byte res = Byte.MIN_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = (byte) VectorMath.maxUnsigned(res, a[i]); + } + + return res; + } + + static byte UMAXReduceAllMasked(byte[] a, boolean[] mask) { + byte res = Byte.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (byte) VectorMath.maxUnsigned(res, UMAXReduceMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "byteUnaryOpMaskProvider") + static void UMAXReduceByte64VectorTestsMasked(IntFunction<byte[]> fa, IntFunction<boolean[]> fm) { + byte[] a = fa.apply(SPECIES.length()); + byte[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask<Byte> vmask = VectorMask.fromArray(SPECIES, mask, 0); + byte ra = Byte.MIN_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMAX, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Byte.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + ra = (byte) VectorMath.maxUnsigned(ra, av.reduceLanes(VectorOperators.UMAX, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Byte64VectorTests::UMAXReduceMasked, Byte64VectorTests::UMAXReduceAllMasked); + } + static byte FIRST_NONZEROReduce(byte[] a, int idx) { byte res = (byte) 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { diff --git a/test/jdk/jdk/incubator/vector/ByteMaxVectorTests.java b/test/jdk/jdk/incubator/vector/ByteMaxVectorTests.java index 2d9d49f32ad..9aaf1b6db95 100644 --- a/test/jdk/jdk/incubator/vector/ByteMaxVectorTests.java +++ b/test/jdk/jdk/incubator/vector/ByteMaxVectorTests.java @@ -3917,6 +3917,184 @@ static void MAXReduceByteMaxVectorTestsMasked(IntFunction<byte[]> fa, IntFunctio ByteMaxVectorTests::MAXReduceMasked, ByteMaxVectorTests::MAXReduceAllMasked); } + static byte UMINReduce(byte[] a, int idx) { + byte res = Byte.MAX_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = (byte) VectorMath.minUnsigned(res, a[i]); + } + + return res; + } + + static byte UMINReduceAll(byte[] a) { + byte res = Byte.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (byte) VectorMath.minUnsigned(res, UMINReduce(a, i)); + } + + return res; + } + + @Test(dataProvider = "byteUnaryOpProvider") + static void UMINReduceByteMaxVectorTests(IntFunction<byte[]> fa) { + byte[] a = fa.apply(SPECIES.length()); + byte[] r = fr.apply(SPECIES.length()); + byte ra = Byte.MAX_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMIN); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Byte.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + ra = (byte) VectorMath.minUnsigned(ra, av.reduceLanes(VectorOperators.UMIN)); + } + } + + assertReductionArraysEquals(r, ra, a, + ByteMaxVectorTests::UMINReduce, ByteMaxVectorTests::UMINReduceAll); + } + + static byte UMINReduceMasked(byte[] a, int idx, boolean[] mask) { + byte res = Byte.MAX_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = (byte) VectorMath.minUnsigned(res, a[i]); + } + + return res; + } + + static byte UMINReduceAllMasked(byte[] a, boolean[] mask) { + byte res = Byte.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (byte) VectorMath.minUnsigned(res, UMINReduceMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "byteUnaryOpMaskProvider") + static void UMINReduceByteMaxVectorTestsMasked(IntFunction<byte[]> fa, IntFunction<boolean[]> fm) { + byte[] a = fa.apply(SPECIES.length()); + byte[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask<Byte> vmask = VectorMask.fromArray(SPECIES, mask, 0); + byte ra = Byte.MAX_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMIN, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Byte.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + ra = (byte) VectorMath.minUnsigned(ra, av.reduceLanes(VectorOperators.UMIN, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + ByteMaxVectorTests::UMINReduceMasked, ByteMaxVectorTests::UMINReduceAllMasked); + } + + static byte UMAXReduce(byte[] a, int idx) { + byte res = Byte.MIN_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = (byte) VectorMath.maxUnsigned(res, a[i]); + } + + return res; + } + + static byte UMAXReduceAll(byte[] a) { + byte res = Byte.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (byte) VectorMath.maxUnsigned(res, UMAXReduce(a, i)); + } + + return res; + } + + @Test(dataProvider = "byteUnaryOpProvider") + static void UMAXReduceByteMaxVectorTests(IntFunction<byte[]> fa) { + byte[] a = fa.apply(SPECIES.length()); + byte[] r = fr.apply(SPECIES.length()); + byte ra = Byte.MIN_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMAX); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Byte.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + ra = (byte) VectorMath.maxUnsigned(ra, av.reduceLanes(VectorOperators.UMAX)); + } + } + + assertReductionArraysEquals(r, ra, a, + ByteMaxVectorTests::UMAXReduce, ByteMaxVectorTests::UMAXReduceAll); + } + + static byte UMAXReduceMasked(byte[] a, int idx, boolean[] mask) { + byte res = Byte.MIN_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = (byte) VectorMath.maxUnsigned(res, a[i]); + } + + return res; + } + + static byte UMAXReduceAllMasked(byte[] a, boolean[] mask) { + byte res = Byte.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (byte) VectorMath.maxUnsigned(res, UMAXReduceMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "byteUnaryOpMaskProvider") + static void UMAXReduceByteMaxVectorTestsMasked(IntFunction<byte[]> fa, IntFunction<boolean[]> fm) { + byte[] a = fa.apply(SPECIES.length()); + byte[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask<Byte> vmask = VectorMask.fromArray(SPECIES, mask, 0); + byte ra = Byte.MIN_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMAX, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Byte.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + ra = (byte) VectorMath.maxUnsigned(ra, av.reduceLanes(VectorOperators.UMAX, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + ByteMaxVectorTests::UMAXReduceMasked, ByteMaxVectorTests::UMAXReduceAllMasked); + } + static byte FIRST_NONZEROReduce(byte[] a, int idx) { byte res = (byte) 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { diff --git a/test/jdk/jdk/incubator/vector/Int128VectorTests.java b/test/jdk/jdk/incubator/vector/Int128VectorTests.java index 028e757e853..4f8f296c519 100644 --- a/test/jdk/jdk/incubator/vector/Int128VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Int128VectorTests.java @@ -3956,6 +3956,184 @@ static void MAXReduceInt128VectorTestsMasked(IntFunction<int[]> fa, IntFunction< Int128VectorTests::MAXReduceMasked, Int128VectorTests::MAXReduceAllMasked); } + static int UMINReduce(int[] a, int idx) { + int res = Integer.MAX_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = (int) VectorMath.minUnsigned(res, a[i]); + } + + return res; + } + + static int UMINReduceAll(int[] a) { + int res = Integer.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (int) VectorMath.minUnsigned(res, UMINReduce(a, i)); + } + + return res; + } + + @Test(dataProvider = "intUnaryOpProvider") + static void UMINReduceInt128VectorTests(IntFunction<int[]> fa) { + int[] a = fa.apply(SPECIES.length()); + int[] r = fr.apply(SPECIES.length()); + int ra = Integer.MAX_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMIN); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Integer.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + ra = (int) VectorMath.minUnsigned(ra, av.reduceLanes(VectorOperators.UMIN)); + } + } + + assertReductionArraysEquals(r, ra, a, + Int128VectorTests::UMINReduce, Int128VectorTests::UMINReduceAll); + } + + static int UMINReduceMasked(int[] a, int idx, boolean[] mask) { + int res = Integer.MAX_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = (int) VectorMath.minUnsigned(res, a[i]); + } + + return res; + } + + static int UMINReduceAllMasked(int[] a, boolean[] mask) { + int res = Integer.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (int) VectorMath.minUnsigned(res, UMINReduceMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "intUnaryOpMaskProvider") + static void UMINReduceInt128VectorTestsMasked(IntFunction<int[]> fa, IntFunction<boolean[]> fm) { + int[] a = fa.apply(SPECIES.length()); + int[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask<Integer> vmask = VectorMask.fromArray(SPECIES, mask, 0); + int ra = Integer.MAX_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMIN, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Integer.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + ra = (int) VectorMath.minUnsigned(ra, av.reduceLanes(VectorOperators.UMIN, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Int128VectorTests::UMINReduceMasked, Int128VectorTests::UMINReduceAllMasked); + } + + static int UMAXReduce(int[] a, int idx) { + int res = Integer.MIN_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = (int) VectorMath.maxUnsigned(res, a[i]); + } + + return res; + } + + static int UMAXReduceAll(int[] a) { + int res = Integer.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (int) VectorMath.maxUnsigned(res, UMAXReduce(a, i)); + } + + return res; + } + + @Test(dataProvider = "intUnaryOpProvider") + static void UMAXReduceInt128VectorTests(IntFunction<int[]> fa) { + int[] a = fa.apply(SPECIES.length()); + int[] r = fr.apply(SPECIES.length()); + int ra = Integer.MIN_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMAX); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Integer.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + ra = (int) VectorMath.maxUnsigned(ra, av.reduceLanes(VectorOperators.UMAX)); + } + } + + assertReductionArraysEquals(r, ra, a, + Int128VectorTests::UMAXReduce, Int128VectorTests::UMAXReduceAll); + } + + static int UMAXReduceMasked(int[] a, int idx, boolean[] mask) { + int res = Integer.MIN_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = (int) VectorMath.maxUnsigned(res, a[i]); + } + + return res; + } + + static int UMAXReduceAllMasked(int[] a, boolean[] mask) { + int res = Integer.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (int) VectorMath.maxUnsigned(res, UMAXReduceMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "intUnaryOpMaskProvider") + static void UMAXReduceInt128VectorTestsMasked(IntFunction<int[]> fa, IntFunction<boolean[]> fm) { + int[] a = fa.apply(SPECIES.length()); + int[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask<Integer> vmask = VectorMask.fromArray(SPECIES, mask, 0); + int ra = Integer.MIN_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMAX, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Integer.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + ra = (int) VectorMath.maxUnsigned(ra, av.reduceLanes(VectorOperators.UMAX, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Int128VectorTests::UMAXReduceMasked, Int128VectorTests::UMAXReduceAllMasked); + } + static int FIRST_NONZEROReduce(int[] a, int idx) { int res = (int) 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { diff --git a/test/jdk/jdk/incubator/vector/Int256VectorTests.java b/test/jdk/jdk/incubator/vector/Int256VectorTests.java index 6dab8a39873..312227c54e1 100644 --- a/test/jdk/jdk/incubator/vector/Int256VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Int256VectorTests.java @@ -3956,6 +3956,184 @@ static void MAXReduceInt256VectorTestsMasked(IntFunction<int[]> fa, IntFunction< Int256VectorTests::MAXReduceMasked, Int256VectorTests::MAXReduceAllMasked); } + static int UMINReduce(int[] a, int idx) { + int res = Integer.MAX_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = (int) VectorMath.minUnsigned(res, a[i]); + } + + return res; + } + + static int UMINReduceAll(int[] a) { + int res = Integer.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (int) VectorMath.minUnsigned(res, UMINReduce(a, i)); + } + + return res; + } + + @Test(dataProvider = "intUnaryOpProvider") + static void UMINReduceInt256VectorTests(IntFunction<int[]> fa) { + int[] a = fa.apply(SPECIES.length()); + int[] r = fr.apply(SPECIES.length()); + int ra = Integer.MAX_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMIN); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Integer.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + ra = (int) VectorMath.minUnsigned(ra, av.reduceLanes(VectorOperators.UMIN)); + } + } + + assertReductionArraysEquals(r, ra, a, + Int256VectorTests::UMINReduce, Int256VectorTests::UMINReduceAll); + } + + static int UMINReduceMasked(int[] a, int idx, boolean[] mask) { + int res = Integer.MAX_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = (int) VectorMath.minUnsigned(res, a[i]); + } + + return res; + } + + static int UMINReduceAllMasked(int[] a, boolean[] mask) { + int res = Integer.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (int) VectorMath.minUnsigned(res, UMINReduceMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "intUnaryOpMaskProvider") + static void UMINReduceInt256VectorTestsMasked(IntFunction<int[]> fa, IntFunction<boolean[]> fm) { + int[] a = fa.apply(SPECIES.length()); + int[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask<Integer> vmask = VectorMask.fromArray(SPECIES, mask, 0); + int ra = Integer.MAX_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMIN, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Integer.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + ra = (int) VectorMath.minUnsigned(ra, av.reduceLanes(VectorOperators.UMIN, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Int256VectorTests::UMINReduceMasked, Int256VectorTests::UMINReduceAllMasked); + } + + static int UMAXReduce(int[] a, int idx) { + int res = Integer.MIN_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = (int) VectorMath.maxUnsigned(res, a[i]); + } + + return res; + } + + static int UMAXReduceAll(int[] a) { + int res = Integer.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (int) VectorMath.maxUnsigned(res, UMAXReduce(a, i)); + } + + return res; + } + + @Test(dataProvider = "intUnaryOpProvider") + static void UMAXReduceInt256VectorTests(IntFunction<int[]> fa) { + int[] a = fa.apply(SPECIES.length()); + int[] r = fr.apply(SPECIES.length()); + int ra = Integer.MIN_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMAX); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Integer.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + ra = (int) VectorMath.maxUnsigned(ra, av.reduceLanes(VectorOperators.UMAX)); + } + } + + assertReductionArraysEquals(r, ra, a, + Int256VectorTests::UMAXReduce, Int256VectorTests::UMAXReduceAll); + } + + static int UMAXReduceMasked(int[] a, int idx, boolean[] mask) { + int res = Integer.MIN_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = (int) VectorMath.maxUnsigned(res, a[i]); + } + + return res; + } + + static int UMAXReduceAllMasked(int[] a, boolean[] mask) { + int res = Integer.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (int) VectorMath.maxUnsigned(res, UMAXReduceMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "intUnaryOpMaskProvider") + static void UMAXReduceInt256VectorTestsMasked(IntFunction<int[]> fa, IntFunction<boolean[]> fm) { + int[] a = fa.apply(SPECIES.length()); + int[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask<Integer> vmask = VectorMask.fromArray(SPECIES, mask, 0); + int ra = Integer.MIN_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMAX, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Integer.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + ra = (int) VectorMath.maxUnsigned(ra, av.reduceLanes(VectorOperators.UMAX, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Int256VectorTests::UMAXReduceMasked, Int256VectorTests::UMAXReduceAllMasked); + } + static int FIRST_NONZEROReduce(int[] a, int idx) { int res = (int) 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { diff --git a/test/jdk/jdk/incubator/vector/Int512VectorTests.java b/test/jdk/jdk/incubator/vector/Int512VectorTests.java index 0c86655ff22..3e5b51180b6 100644 --- a/test/jdk/jdk/incubator/vector/Int512VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Int512VectorTests.java @@ -3956,6 +3956,184 @@ static void MAXReduceInt512VectorTestsMasked(IntFunction<int[]> fa, IntFunction< Int512VectorTests::MAXReduceMasked, Int512VectorTests::MAXReduceAllMasked); } + static int UMINReduce(int[] a, int idx) { + int res = Integer.MAX_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = (int) VectorMath.minUnsigned(res, a[i]); + } + + return res; + } + + static int UMINReduceAll(int[] a) { + int res = Integer.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (int) VectorMath.minUnsigned(res, UMINReduce(a, i)); + } + + return res; + } + + @Test(dataProvider = "intUnaryOpProvider") + static void UMINReduceInt512VectorTests(IntFunction<int[]> fa) { + int[] a = fa.apply(SPECIES.length()); + int[] r = fr.apply(SPECIES.length()); + int ra = Integer.MAX_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMIN); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Integer.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + ra = (int) VectorMath.minUnsigned(ra, av.reduceLanes(VectorOperators.UMIN)); + } + } + + assertReductionArraysEquals(r, ra, a, + Int512VectorTests::UMINReduce, Int512VectorTests::UMINReduceAll); + } + + static int UMINReduceMasked(int[] a, int idx, boolean[] mask) { + int res = Integer.MAX_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = (int) VectorMath.minUnsigned(res, a[i]); + } + + return res; + } + + static int UMINReduceAllMasked(int[] a, boolean[] mask) { + int res = Integer.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (int) VectorMath.minUnsigned(res, UMINReduceMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "intUnaryOpMaskProvider") + static void UMINReduceInt512VectorTestsMasked(IntFunction<int[]> fa, IntFunction<boolean[]> fm) { + int[] a = fa.apply(SPECIES.length()); + int[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask<Integer> vmask = VectorMask.fromArray(SPECIES, mask, 0); + int ra = Integer.MAX_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMIN, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Integer.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + ra = (int) VectorMath.minUnsigned(ra, av.reduceLanes(VectorOperators.UMIN, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Int512VectorTests::UMINReduceMasked, Int512VectorTests::UMINReduceAllMasked); + } + + static int UMAXReduce(int[] a, int idx) { + int res = Integer.MIN_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = (int) VectorMath.maxUnsigned(res, a[i]); + } + + return res; + } + + static int UMAXReduceAll(int[] a) { + int res = Integer.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (int) VectorMath.maxUnsigned(res, UMAXReduce(a, i)); + } + + return res; + } + + @Test(dataProvider = "intUnaryOpProvider") + static void UMAXReduceInt512VectorTests(IntFunction<int[]> fa) { + int[] a = fa.apply(SPECIES.length()); + int[] r = fr.apply(SPECIES.length()); + int ra = Integer.MIN_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMAX); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Integer.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + ra = (int) VectorMath.maxUnsigned(ra, av.reduceLanes(VectorOperators.UMAX)); + } + } + + assertReductionArraysEquals(r, ra, a, + Int512VectorTests::UMAXReduce, Int512VectorTests::UMAXReduceAll); + } + + static int UMAXReduceMasked(int[] a, int idx, boolean[] mask) { + int res = Integer.MIN_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = (int) VectorMath.maxUnsigned(res, a[i]); + } + + return res; + } + + static int UMAXReduceAllMasked(int[] a, boolean[] mask) { + int res = Integer.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (int) VectorMath.maxUnsigned(res, UMAXReduceMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "intUnaryOpMaskProvider") + static void UMAXReduceInt512VectorTestsMasked(IntFunction<int[]> fa, IntFunction<boolean[]> fm) { + int[] a = fa.apply(SPECIES.length()); + int[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask<Integer> vmask = VectorMask.fromArray(SPECIES, mask, 0); + int ra = Integer.MIN_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMAX, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Integer.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + ra = (int) VectorMath.maxUnsigned(ra, av.reduceLanes(VectorOperators.UMAX, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Int512VectorTests::UMAXReduceMasked, Int512VectorTests::UMAXReduceAllMasked); + } + static int FIRST_NONZEROReduce(int[] a, int idx) { int res = (int) 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { diff --git a/test/jdk/jdk/incubator/vector/Int64VectorTests.java b/test/jdk/jdk/incubator/vector/Int64VectorTests.java index b2cb3698f62..fccad11d4d6 100644 --- a/test/jdk/jdk/incubator/vector/Int64VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Int64VectorTests.java @@ -3956,6 +3956,184 @@ static void MAXReduceInt64VectorTestsMasked(IntFunction<int[]> fa, IntFunction<b Int64VectorTests::MAXReduceMasked, Int64VectorTests::MAXReduceAllMasked); } + static int UMINReduce(int[] a, int idx) { + int res = Integer.MAX_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = (int) VectorMath.minUnsigned(res, a[i]); + } + + return res; + } + + static int UMINReduceAll(int[] a) { + int res = Integer.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (int) VectorMath.minUnsigned(res, UMINReduce(a, i)); + } + + return res; + } + + @Test(dataProvider = "intUnaryOpProvider") + static void UMINReduceInt64VectorTests(IntFunction<int[]> fa) { + int[] a = fa.apply(SPECIES.length()); + int[] r = fr.apply(SPECIES.length()); + int ra = Integer.MAX_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMIN); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Integer.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + ra = (int) VectorMath.minUnsigned(ra, av.reduceLanes(VectorOperators.UMIN)); + } + } + + assertReductionArraysEquals(r, ra, a, + Int64VectorTests::UMINReduce, Int64VectorTests::UMINReduceAll); + } + + static int UMINReduceMasked(int[] a, int idx, boolean[] mask) { + int res = Integer.MAX_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = (int) VectorMath.minUnsigned(res, a[i]); + } + + return res; + } + + static int UMINReduceAllMasked(int[] a, boolean[] mask) { + int res = Integer.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (int) VectorMath.minUnsigned(res, UMINReduceMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "intUnaryOpMaskProvider") + static void UMINReduceInt64VectorTestsMasked(IntFunction<int[]> fa, IntFunction<boolean[]> fm) { + int[] a = fa.apply(SPECIES.length()); + int[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask<Integer> vmask = VectorMask.fromArray(SPECIES, mask, 0); + int ra = Integer.MAX_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMIN, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Integer.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + ra = (int) VectorMath.minUnsigned(ra, av.reduceLanes(VectorOperators.UMIN, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Int64VectorTests::UMINReduceMasked, Int64VectorTests::UMINReduceAllMasked); + } + + static int UMAXReduce(int[] a, int idx) { + int res = Integer.MIN_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = (int) VectorMath.maxUnsigned(res, a[i]); + } + + return res; + } + + static int UMAXReduceAll(int[] a) { + int res = Integer.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (int) VectorMath.maxUnsigned(res, UMAXReduce(a, i)); + } + + return res; + } + + @Test(dataProvider = "intUnaryOpProvider") + static void UMAXReduceInt64VectorTests(IntFunction<int[]> fa) { + int[] a = fa.apply(SPECIES.length()); + int[] r = fr.apply(SPECIES.length()); + int ra = Integer.MIN_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMAX); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Integer.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + ra = (int) VectorMath.maxUnsigned(ra, av.reduceLanes(VectorOperators.UMAX)); + } + } + + assertReductionArraysEquals(r, ra, a, + Int64VectorTests::UMAXReduce, Int64VectorTests::UMAXReduceAll); + } + + static int UMAXReduceMasked(int[] a, int idx, boolean[] mask) { + int res = Integer.MIN_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = (int) VectorMath.maxUnsigned(res, a[i]); + } + + return res; + } + + static int UMAXReduceAllMasked(int[] a, boolean[] mask) { + int res = Integer.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (int) VectorMath.maxUnsigned(res, UMAXReduceMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "intUnaryOpMaskProvider") + static void UMAXReduceInt64VectorTestsMasked(IntFunction<int[]> fa, IntFunction<boolean[]> fm) { + int[] a = fa.apply(SPECIES.length()); + int[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask<Integer> vmask = VectorMask.fromArray(SPECIES, mask, 0); + int ra = Integer.MIN_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMAX, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Integer.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + ra = (int) VectorMath.maxUnsigned(ra, av.reduceLanes(VectorOperators.UMAX, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Int64VectorTests::UMAXReduceMasked, Int64VectorTests::UMAXReduceAllMasked); + } + static int FIRST_NONZEROReduce(int[] a, int idx) { int res = (int) 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { diff --git a/test/jdk/jdk/incubator/vector/IntMaxVectorTests.java b/test/jdk/jdk/incubator/vector/IntMaxVectorTests.java index fc0f6c1c139..3254c2fb86c 100644 --- a/test/jdk/jdk/incubator/vector/IntMaxVectorTests.java +++ b/test/jdk/jdk/incubator/vector/IntMaxVectorTests.java @@ -3961,6 +3961,184 @@ static void MAXReduceIntMaxVectorTestsMasked(IntFunction<int[]> fa, IntFunction< IntMaxVectorTests::MAXReduceMasked, IntMaxVectorTests::MAXReduceAllMasked); } + static int UMINReduce(int[] a, int idx) { + int res = Integer.MAX_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = (int) VectorMath.minUnsigned(res, a[i]); + } + + return res; + } + + static int UMINReduceAll(int[] a) { + int res = Integer.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (int) VectorMath.minUnsigned(res, UMINReduce(a, i)); + } + + return res; + } + + @Test(dataProvider = "intUnaryOpProvider") + static void UMINReduceIntMaxVectorTests(IntFunction<int[]> fa) { + int[] a = fa.apply(SPECIES.length()); + int[] r = fr.apply(SPECIES.length()); + int ra = Integer.MAX_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMIN); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Integer.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + ra = (int) VectorMath.minUnsigned(ra, av.reduceLanes(VectorOperators.UMIN)); + } + } + + assertReductionArraysEquals(r, ra, a, + IntMaxVectorTests::UMINReduce, IntMaxVectorTests::UMINReduceAll); + } + + static int UMINReduceMasked(int[] a, int idx, boolean[] mask) { + int res = Integer.MAX_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = (int) VectorMath.minUnsigned(res, a[i]); + } + + return res; + } + + static int UMINReduceAllMasked(int[] a, boolean[] mask) { + int res = Integer.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (int) VectorMath.minUnsigned(res, UMINReduceMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "intUnaryOpMaskProvider") + static void UMINReduceIntMaxVectorTestsMasked(IntFunction<int[]> fa, IntFunction<boolean[]> fm) { + int[] a = fa.apply(SPECIES.length()); + int[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask<Integer> vmask = VectorMask.fromArray(SPECIES, mask, 0); + int ra = Integer.MAX_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMIN, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Integer.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + ra = (int) VectorMath.minUnsigned(ra, av.reduceLanes(VectorOperators.UMIN, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + IntMaxVectorTests::UMINReduceMasked, IntMaxVectorTests::UMINReduceAllMasked); + } + + static int UMAXReduce(int[] a, int idx) { + int res = Integer.MIN_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = (int) VectorMath.maxUnsigned(res, a[i]); + } + + return res; + } + + static int UMAXReduceAll(int[] a) { + int res = Integer.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (int) VectorMath.maxUnsigned(res, UMAXReduce(a, i)); + } + + return res; + } + + @Test(dataProvider = "intUnaryOpProvider") + static void UMAXReduceIntMaxVectorTests(IntFunction<int[]> fa) { + int[] a = fa.apply(SPECIES.length()); + int[] r = fr.apply(SPECIES.length()); + int ra = Integer.MIN_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMAX); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Integer.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + ra = (int) VectorMath.maxUnsigned(ra, av.reduceLanes(VectorOperators.UMAX)); + } + } + + assertReductionArraysEquals(r, ra, a, + IntMaxVectorTests::UMAXReduce, IntMaxVectorTests::UMAXReduceAll); + } + + static int UMAXReduceMasked(int[] a, int idx, boolean[] mask) { + int res = Integer.MIN_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = (int) VectorMath.maxUnsigned(res, a[i]); + } + + return res; + } + + static int UMAXReduceAllMasked(int[] a, boolean[] mask) { + int res = Integer.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (int) VectorMath.maxUnsigned(res, UMAXReduceMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "intUnaryOpMaskProvider") + static void UMAXReduceIntMaxVectorTestsMasked(IntFunction<int[]> fa, IntFunction<boolean[]> fm) { + int[] a = fa.apply(SPECIES.length()); + int[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask<Integer> vmask = VectorMask.fromArray(SPECIES, mask, 0); + int ra = Integer.MIN_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMAX, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Integer.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + ra = (int) VectorMath.maxUnsigned(ra, av.reduceLanes(VectorOperators.UMAX, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + IntMaxVectorTests::UMAXReduceMasked, IntMaxVectorTests::UMAXReduceAllMasked); + } + static int FIRST_NONZEROReduce(int[] a, int idx) { int res = (int) 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { diff --git a/test/jdk/jdk/incubator/vector/Long128VectorTests.java b/test/jdk/jdk/incubator/vector/Long128VectorTests.java index 3694128877a..09fdc3c1979 100644 --- a/test/jdk/jdk/incubator/vector/Long128VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Long128VectorTests.java @@ -3978,6 +3978,184 @@ static void MAXReduceLong128VectorTestsMasked(IntFunction<long[]> fa, IntFunctio Long128VectorTests::MAXReduceMasked, Long128VectorTests::MAXReduceAllMasked); } + static long UMINReduce(long[] a, int idx) { + long res = Long.MAX_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = (long) VectorMath.minUnsigned(res, a[i]); + } + + return res; + } + + static long UMINReduceAll(long[] a) { + long res = Long.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (long) VectorMath.minUnsigned(res, UMINReduce(a, i)); + } + + return res; + } + + @Test(dataProvider = "longUnaryOpProvider") + static void UMINReduceLong128VectorTests(IntFunction<long[]> fa) { + long[] a = fa.apply(SPECIES.length()); + long[] r = fr.apply(SPECIES.length()); + long ra = Long.MAX_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMIN); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Long.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + ra = (long) VectorMath.minUnsigned(ra, av.reduceLanes(VectorOperators.UMIN)); + } + } + + assertReductionArraysEquals(r, ra, a, + Long128VectorTests::UMINReduce, Long128VectorTests::UMINReduceAll); + } + + static long UMINReduceMasked(long[] a, int idx, boolean[] mask) { + long res = Long.MAX_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = (long) VectorMath.minUnsigned(res, a[i]); + } + + return res; + } + + static long UMINReduceAllMasked(long[] a, boolean[] mask) { + long res = Long.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (long) VectorMath.minUnsigned(res, UMINReduceMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "longUnaryOpMaskProvider") + static void UMINReduceLong128VectorTestsMasked(IntFunction<long[]> fa, IntFunction<boolean[]> fm) { + long[] a = fa.apply(SPECIES.length()); + long[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask<Long> vmask = VectorMask.fromArray(SPECIES, mask, 0); + long ra = Long.MAX_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMIN, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Long.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + ra = (long) VectorMath.minUnsigned(ra, av.reduceLanes(VectorOperators.UMIN, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Long128VectorTests::UMINReduceMasked, Long128VectorTests::UMINReduceAllMasked); + } + + static long UMAXReduce(long[] a, int idx) { + long res = Long.MIN_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = (long) VectorMath.maxUnsigned(res, a[i]); + } + + return res; + } + + static long UMAXReduceAll(long[] a) { + long res = Long.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (long) VectorMath.maxUnsigned(res, UMAXReduce(a, i)); + } + + return res; + } + + @Test(dataProvider = "longUnaryOpProvider") + static void UMAXReduceLong128VectorTests(IntFunction<long[]> fa) { + long[] a = fa.apply(SPECIES.length()); + long[] r = fr.apply(SPECIES.length()); + long ra = Long.MIN_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMAX); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Long.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + ra = (long) VectorMath.maxUnsigned(ra, av.reduceLanes(VectorOperators.UMAX)); + } + } + + assertReductionArraysEquals(r, ra, a, + Long128VectorTests::UMAXReduce, Long128VectorTests::UMAXReduceAll); + } + + static long UMAXReduceMasked(long[] a, int idx, boolean[] mask) { + long res = Long.MIN_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = (long) VectorMath.maxUnsigned(res, a[i]); + } + + return res; + } + + static long UMAXReduceAllMasked(long[] a, boolean[] mask) { + long res = Long.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (long) VectorMath.maxUnsigned(res, UMAXReduceMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "longUnaryOpMaskProvider") + static void UMAXReduceLong128VectorTestsMasked(IntFunction<long[]> fa, IntFunction<boolean[]> fm) { + long[] a = fa.apply(SPECIES.length()); + long[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask<Long> vmask = VectorMask.fromArray(SPECIES, mask, 0); + long ra = Long.MIN_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMAX, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Long.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + ra = (long) VectorMath.maxUnsigned(ra, av.reduceLanes(VectorOperators.UMAX, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Long128VectorTests::UMAXReduceMasked, Long128VectorTests::UMAXReduceAllMasked); + } + static long FIRST_NONZEROReduce(long[] a, int idx) { long res = (long) 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { diff --git a/test/jdk/jdk/incubator/vector/Long256VectorTests.java b/test/jdk/jdk/incubator/vector/Long256VectorTests.java index 1fc441680fd..7dd0da772ed 100644 --- a/test/jdk/jdk/incubator/vector/Long256VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Long256VectorTests.java @@ -3978,6 +3978,184 @@ static void MAXReduceLong256VectorTestsMasked(IntFunction<long[]> fa, IntFunctio Long256VectorTests::MAXReduceMasked, Long256VectorTests::MAXReduceAllMasked); } + static long UMINReduce(long[] a, int idx) { + long res = Long.MAX_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = (long) VectorMath.minUnsigned(res, a[i]); + } + + return res; + } + + static long UMINReduceAll(long[] a) { + long res = Long.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (long) VectorMath.minUnsigned(res, UMINReduce(a, i)); + } + + return res; + } + + @Test(dataProvider = "longUnaryOpProvider") + static void UMINReduceLong256VectorTests(IntFunction<long[]> fa) { + long[] a = fa.apply(SPECIES.length()); + long[] r = fr.apply(SPECIES.length()); + long ra = Long.MAX_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMIN); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Long.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + ra = (long) VectorMath.minUnsigned(ra, av.reduceLanes(VectorOperators.UMIN)); + } + } + + assertReductionArraysEquals(r, ra, a, + Long256VectorTests::UMINReduce, Long256VectorTests::UMINReduceAll); + } + + static long UMINReduceMasked(long[] a, int idx, boolean[] mask) { + long res = Long.MAX_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = (long) VectorMath.minUnsigned(res, a[i]); + } + + return res; + } + + static long UMINReduceAllMasked(long[] a, boolean[] mask) { + long res = Long.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (long) VectorMath.minUnsigned(res, UMINReduceMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "longUnaryOpMaskProvider") + static void UMINReduceLong256VectorTestsMasked(IntFunction<long[]> fa, IntFunction<boolean[]> fm) { + long[] a = fa.apply(SPECIES.length()); + long[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask<Long> vmask = VectorMask.fromArray(SPECIES, mask, 0); + long ra = Long.MAX_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMIN, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Long.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + ra = (long) VectorMath.minUnsigned(ra, av.reduceLanes(VectorOperators.UMIN, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Long256VectorTests::UMINReduceMasked, Long256VectorTests::UMINReduceAllMasked); + } + + static long UMAXReduce(long[] a, int idx) { + long res = Long.MIN_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = (long) VectorMath.maxUnsigned(res, a[i]); + } + + return res; + } + + static long UMAXReduceAll(long[] a) { + long res = Long.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (long) VectorMath.maxUnsigned(res, UMAXReduce(a, i)); + } + + return res; + } + + @Test(dataProvider = "longUnaryOpProvider") + static void UMAXReduceLong256VectorTests(IntFunction<long[]> fa) { + long[] a = fa.apply(SPECIES.length()); + long[] r = fr.apply(SPECIES.length()); + long ra = Long.MIN_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMAX); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Long.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + ra = (long) VectorMath.maxUnsigned(ra, av.reduceLanes(VectorOperators.UMAX)); + } + } + + assertReductionArraysEquals(r, ra, a, + Long256VectorTests::UMAXReduce, Long256VectorTests::UMAXReduceAll); + } + + static long UMAXReduceMasked(long[] a, int idx, boolean[] mask) { + long res = Long.MIN_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = (long) VectorMath.maxUnsigned(res, a[i]); + } + + return res; + } + + static long UMAXReduceAllMasked(long[] a, boolean[] mask) { + long res = Long.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (long) VectorMath.maxUnsigned(res, UMAXReduceMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "longUnaryOpMaskProvider") + static void UMAXReduceLong256VectorTestsMasked(IntFunction<long[]> fa, IntFunction<boolean[]> fm) { + long[] a = fa.apply(SPECIES.length()); + long[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask<Long> vmask = VectorMask.fromArray(SPECIES, mask, 0); + long ra = Long.MIN_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMAX, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Long.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + ra = (long) VectorMath.maxUnsigned(ra, av.reduceLanes(VectorOperators.UMAX, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Long256VectorTests::UMAXReduceMasked, Long256VectorTests::UMAXReduceAllMasked); + } + static long FIRST_NONZEROReduce(long[] a, int idx) { long res = (long) 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { diff --git a/test/jdk/jdk/incubator/vector/Long512VectorTests.java b/test/jdk/jdk/incubator/vector/Long512VectorTests.java index 81d538a55c4..360e822e121 100644 --- a/test/jdk/jdk/incubator/vector/Long512VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Long512VectorTests.java @@ -3978,6 +3978,184 @@ static void MAXReduceLong512VectorTestsMasked(IntFunction<long[]> fa, IntFunctio Long512VectorTests::MAXReduceMasked, Long512VectorTests::MAXReduceAllMasked); } + static long UMINReduce(long[] a, int idx) { + long res = Long.MAX_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = (long) VectorMath.minUnsigned(res, a[i]); + } + + return res; + } + + static long UMINReduceAll(long[] a) { + long res = Long.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (long) VectorMath.minUnsigned(res, UMINReduce(a, i)); + } + + return res; + } + + @Test(dataProvider = "longUnaryOpProvider") + static void UMINReduceLong512VectorTests(IntFunction<long[]> fa) { + long[] a = fa.apply(SPECIES.length()); + long[] r = fr.apply(SPECIES.length()); + long ra = Long.MAX_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMIN); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Long.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + ra = (long) VectorMath.minUnsigned(ra, av.reduceLanes(VectorOperators.UMIN)); + } + } + + assertReductionArraysEquals(r, ra, a, + Long512VectorTests::UMINReduce, Long512VectorTests::UMINReduceAll); + } + + static long UMINReduceMasked(long[] a, int idx, boolean[] mask) { + long res = Long.MAX_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = (long) VectorMath.minUnsigned(res, a[i]); + } + + return res; + } + + static long UMINReduceAllMasked(long[] a, boolean[] mask) { + long res = Long.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (long) VectorMath.minUnsigned(res, UMINReduceMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "longUnaryOpMaskProvider") + static void UMINReduceLong512VectorTestsMasked(IntFunction<long[]> fa, IntFunction<boolean[]> fm) { + long[] a = fa.apply(SPECIES.length()); + long[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask<Long> vmask = VectorMask.fromArray(SPECIES, mask, 0); + long ra = Long.MAX_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMIN, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Long.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + ra = (long) VectorMath.minUnsigned(ra, av.reduceLanes(VectorOperators.UMIN, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Long512VectorTests::UMINReduceMasked, Long512VectorTests::UMINReduceAllMasked); + } + + static long UMAXReduce(long[] a, int idx) { + long res = Long.MIN_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = (long) VectorMath.maxUnsigned(res, a[i]); + } + + return res; + } + + static long UMAXReduceAll(long[] a) { + long res = Long.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (long) VectorMath.maxUnsigned(res, UMAXReduce(a, i)); + } + + return res; + } + + @Test(dataProvider = "longUnaryOpProvider") + static void UMAXReduceLong512VectorTests(IntFunction<long[]> fa) { + long[] a = fa.apply(SPECIES.length()); + long[] r = fr.apply(SPECIES.length()); + long ra = Long.MIN_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMAX); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Long.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + ra = (long) VectorMath.maxUnsigned(ra, av.reduceLanes(VectorOperators.UMAX)); + } + } + + assertReductionArraysEquals(r, ra, a, + Long512VectorTests::UMAXReduce, Long512VectorTests::UMAXReduceAll); + } + + static long UMAXReduceMasked(long[] a, int idx, boolean[] mask) { + long res = Long.MIN_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = (long) VectorMath.maxUnsigned(res, a[i]); + } + + return res; + } + + static long UMAXReduceAllMasked(long[] a, boolean[] mask) { + long res = Long.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (long) VectorMath.maxUnsigned(res, UMAXReduceMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "longUnaryOpMaskProvider") + static void UMAXReduceLong512VectorTestsMasked(IntFunction<long[]> fa, IntFunction<boolean[]> fm) { + long[] a = fa.apply(SPECIES.length()); + long[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask<Long> vmask = VectorMask.fromArray(SPECIES, mask, 0); + long ra = Long.MIN_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMAX, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Long.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + ra = (long) VectorMath.maxUnsigned(ra, av.reduceLanes(VectorOperators.UMAX, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Long512VectorTests::UMAXReduceMasked, Long512VectorTests::UMAXReduceAllMasked); + } + static long FIRST_NONZEROReduce(long[] a, int idx) { long res = (long) 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { diff --git a/test/jdk/jdk/incubator/vector/Long64VectorTests.java b/test/jdk/jdk/incubator/vector/Long64VectorTests.java index 1d85fc510d9..31f6fafea7c 100644 --- a/test/jdk/jdk/incubator/vector/Long64VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Long64VectorTests.java @@ -3978,6 +3978,184 @@ static void MAXReduceLong64VectorTestsMasked(IntFunction<long[]> fa, IntFunction Long64VectorTests::MAXReduceMasked, Long64VectorTests::MAXReduceAllMasked); } + static long UMINReduce(long[] a, int idx) { + long res = Long.MAX_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = (long) VectorMath.minUnsigned(res, a[i]); + } + + return res; + } + + static long UMINReduceAll(long[] a) { + long res = Long.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (long) VectorMath.minUnsigned(res, UMINReduce(a, i)); + } + + return res; + } + + @Test(dataProvider = "longUnaryOpProvider") + static void UMINReduceLong64VectorTests(IntFunction<long[]> fa) { + long[] a = fa.apply(SPECIES.length()); + long[] r = fr.apply(SPECIES.length()); + long ra = Long.MAX_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMIN); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Long.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + ra = (long) VectorMath.minUnsigned(ra, av.reduceLanes(VectorOperators.UMIN)); + } + } + + assertReductionArraysEquals(r, ra, a, + Long64VectorTests::UMINReduce, Long64VectorTests::UMINReduceAll); + } + + static long UMINReduceMasked(long[] a, int idx, boolean[] mask) { + long res = Long.MAX_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = (long) VectorMath.minUnsigned(res, a[i]); + } + + return res; + } + + static long UMINReduceAllMasked(long[] a, boolean[] mask) { + long res = Long.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (long) VectorMath.minUnsigned(res, UMINReduceMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "longUnaryOpMaskProvider") + static void UMINReduceLong64VectorTestsMasked(IntFunction<long[]> fa, IntFunction<boolean[]> fm) { + long[] a = fa.apply(SPECIES.length()); + long[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask<Long> vmask = VectorMask.fromArray(SPECIES, mask, 0); + long ra = Long.MAX_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMIN, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Long.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + ra = (long) VectorMath.minUnsigned(ra, av.reduceLanes(VectorOperators.UMIN, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Long64VectorTests::UMINReduceMasked, Long64VectorTests::UMINReduceAllMasked); + } + + static long UMAXReduce(long[] a, int idx) { + long res = Long.MIN_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = (long) VectorMath.maxUnsigned(res, a[i]); + } + + return res; + } + + static long UMAXReduceAll(long[] a) { + long res = Long.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (long) VectorMath.maxUnsigned(res, UMAXReduce(a, i)); + } + + return res; + } + + @Test(dataProvider = "longUnaryOpProvider") + static void UMAXReduceLong64VectorTests(IntFunction<long[]> fa) { + long[] a = fa.apply(SPECIES.length()); + long[] r = fr.apply(SPECIES.length()); + long ra = Long.MIN_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMAX); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Long.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + ra = (long) VectorMath.maxUnsigned(ra, av.reduceLanes(VectorOperators.UMAX)); + } + } + + assertReductionArraysEquals(r, ra, a, + Long64VectorTests::UMAXReduce, Long64VectorTests::UMAXReduceAll); + } + + static long UMAXReduceMasked(long[] a, int idx, boolean[] mask) { + long res = Long.MIN_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = (long) VectorMath.maxUnsigned(res, a[i]); + } + + return res; + } + + static long UMAXReduceAllMasked(long[] a, boolean[] mask) { + long res = Long.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (long) VectorMath.maxUnsigned(res, UMAXReduceMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "longUnaryOpMaskProvider") + static void UMAXReduceLong64VectorTestsMasked(IntFunction<long[]> fa, IntFunction<boolean[]> fm) { + long[] a = fa.apply(SPECIES.length()); + long[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask<Long> vmask = VectorMask.fromArray(SPECIES, mask, 0); + long ra = Long.MIN_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMAX, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Long.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + ra = (long) VectorMath.maxUnsigned(ra, av.reduceLanes(VectorOperators.UMAX, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Long64VectorTests::UMAXReduceMasked, Long64VectorTests::UMAXReduceAllMasked); + } + static long FIRST_NONZEROReduce(long[] a, int idx) { long res = (long) 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { diff --git a/test/jdk/jdk/incubator/vector/LongMaxVectorTests.java b/test/jdk/jdk/incubator/vector/LongMaxVectorTests.java index bae5b968d79..a3cacbe3251 100644 --- a/test/jdk/jdk/incubator/vector/LongMaxVectorTests.java +++ b/test/jdk/jdk/incubator/vector/LongMaxVectorTests.java @@ -3983,6 +3983,184 @@ static void MAXReduceLongMaxVectorTestsMasked(IntFunction<long[]> fa, IntFunctio LongMaxVectorTests::MAXReduceMasked, LongMaxVectorTests::MAXReduceAllMasked); } + static long UMINReduce(long[] a, int idx) { + long res = Long.MAX_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = (long) VectorMath.minUnsigned(res, a[i]); + } + + return res; + } + + static long UMINReduceAll(long[] a) { + long res = Long.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (long) VectorMath.minUnsigned(res, UMINReduce(a, i)); + } + + return res; + } + + @Test(dataProvider = "longUnaryOpProvider") + static void UMINReduceLongMaxVectorTests(IntFunction<long[]> fa) { + long[] a = fa.apply(SPECIES.length()); + long[] r = fr.apply(SPECIES.length()); + long ra = Long.MAX_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMIN); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Long.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + ra = (long) VectorMath.minUnsigned(ra, av.reduceLanes(VectorOperators.UMIN)); + } + } + + assertReductionArraysEquals(r, ra, a, + LongMaxVectorTests::UMINReduce, LongMaxVectorTests::UMINReduceAll); + } + + static long UMINReduceMasked(long[] a, int idx, boolean[] mask) { + long res = Long.MAX_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = (long) VectorMath.minUnsigned(res, a[i]); + } + + return res; + } + + static long UMINReduceAllMasked(long[] a, boolean[] mask) { + long res = Long.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (long) VectorMath.minUnsigned(res, UMINReduceMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "longUnaryOpMaskProvider") + static void UMINReduceLongMaxVectorTestsMasked(IntFunction<long[]> fa, IntFunction<boolean[]> fm) { + long[] a = fa.apply(SPECIES.length()); + long[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask<Long> vmask = VectorMask.fromArray(SPECIES, mask, 0); + long ra = Long.MAX_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMIN, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Long.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + ra = (long) VectorMath.minUnsigned(ra, av.reduceLanes(VectorOperators.UMIN, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + LongMaxVectorTests::UMINReduceMasked, LongMaxVectorTests::UMINReduceAllMasked); + } + + static long UMAXReduce(long[] a, int idx) { + long res = Long.MIN_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = (long) VectorMath.maxUnsigned(res, a[i]); + } + + return res; + } + + static long UMAXReduceAll(long[] a) { + long res = Long.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (long) VectorMath.maxUnsigned(res, UMAXReduce(a, i)); + } + + return res; + } + + @Test(dataProvider = "longUnaryOpProvider") + static void UMAXReduceLongMaxVectorTests(IntFunction<long[]> fa) { + long[] a = fa.apply(SPECIES.length()); + long[] r = fr.apply(SPECIES.length()); + long ra = Long.MIN_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMAX); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Long.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + ra = (long) VectorMath.maxUnsigned(ra, av.reduceLanes(VectorOperators.UMAX)); + } + } + + assertReductionArraysEquals(r, ra, a, + LongMaxVectorTests::UMAXReduce, LongMaxVectorTests::UMAXReduceAll); + } + + static long UMAXReduceMasked(long[] a, int idx, boolean[] mask) { + long res = Long.MIN_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = (long) VectorMath.maxUnsigned(res, a[i]); + } + + return res; + } + + static long UMAXReduceAllMasked(long[] a, boolean[] mask) { + long res = Long.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (long) VectorMath.maxUnsigned(res, UMAXReduceMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "longUnaryOpMaskProvider") + static void UMAXReduceLongMaxVectorTestsMasked(IntFunction<long[]> fa, IntFunction<boolean[]> fm) { + long[] a = fa.apply(SPECIES.length()); + long[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask<Long> vmask = VectorMask.fromArray(SPECIES, mask, 0); + long ra = Long.MIN_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMAX, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Long.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + ra = (long) VectorMath.maxUnsigned(ra, av.reduceLanes(VectorOperators.UMAX, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + LongMaxVectorTests::UMAXReduceMasked, LongMaxVectorTests::UMAXReduceAllMasked); + } + static long FIRST_NONZEROReduce(long[] a, int idx) { long res = (long) 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { diff --git a/test/jdk/jdk/incubator/vector/Short128VectorTests.java b/test/jdk/jdk/incubator/vector/Short128VectorTests.java index 2d6a1fd0a5f..967418181bf 100644 --- a/test/jdk/jdk/incubator/vector/Short128VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Short128VectorTests.java @@ -3903,6 +3903,184 @@ static void MAXReduceShort128VectorTestsMasked(IntFunction<short[]> fa, IntFunct Short128VectorTests::MAXReduceMasked, Short128VectorTests::MAXReduceAllMasked); } + static short UMINReduce(short[] a, int idx) { + short res = Short.MAX_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = (short) VectorMath.minUnsigned(res, a[i]); + } + + return res; + } + + static short UMINReduceAll(short[] a) { + short res = Short.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (short) VectorMath.minUnsigned(res, UMINReduce(a, i)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void UMINReduceShort128VectorTests(IntFunction<short[]> fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + short ra = Short.MAX_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMIN); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Short.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + ra = (short) VectorMath.minUnsigned(ra, av.reduceLanes(VectorOperators.UMIN)); + } + } + + assertReductionArraysEquals(r, ra, a, + Short128VectorTests::UMINReduce, Short128VectorTests::UMINReduceAll); + } + + static short UMINReduceMasked(short[] a, int idx, boolean[] mask) { + short res = Short.MAX_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = (short) VectorMath.minUnsigned(res, a[i]); + } + + return res; + } + + static short UMINReduceAllMasked(short[] a, boolean[] mask) { + short res = Short.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (short) VectorMath.minUnsigned(res, UMINReduceMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void UMINReduceShort128VectorTestsMasked(IntFunction<short[]> fa, IntFunction<boolean[]> fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask<Short> vmask = VectorMask.fromArray(SPECIES, mask, 0); + short ra = Short.MAX_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMIN, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Short.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + ra = (short) VectorMath.minUnsigned(ra, av.reduceLanes(VectorOperators.UMIN, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Short128VectorTests::UMINReduceMasked, Short128VectorTests::UMINReduceAllMasked); + } + + static short UMAXReduce(short[] a, int idx) { + short res = Short.MIN_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = (short) VectorMath.maxUnsigned(res, a[i]); + } + + return res; + } + + static short UMAXReduceAll(short[] a) { + short res = Short.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (short) VectorMath.maxUnsigned(res, UMAXReduce(a, i)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void UMAXReduceShort128VectorTests(IntFunction<short[]> fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + short ra = Short.MIN_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMAX); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Short.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + ra = (short) VectorMath.maxUnsigned(ra, av.reduceLanes(VectorOperators.UMAX)); + } + } + + assertReductionArraysEquals(r, ra, a, + Short128VectorTests::UMAXReduce, Short128VectorTests::UMAXReduceAll); + } + + static short UMAXReduceMasked(short[] a, int idx, boolean[] mask) { + short res = Short.MIN_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = (short) VectorMath.maxUnsigned(res, a[i]); + } + + return res; + } + + static short UMAXReduceAllMasked(short[] a, boolean[] mask) { + short res = Short.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (short) VectorMath.maxUnsigned(res, UMAXReduceMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void UMAXReduceShort128VectorTestsMasked(IntFunction<short[]> fa, IntFunction<boolean[]> fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask<Short> vmask = VectorMask.fromArray(SPECIES, mask, 0); + short ra = Short.MIN_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMAX, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Short.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + ra = (short) VectorMath.maxUnsigned(ra, av.reduceLanes(VectorOperators.UMAX, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Short128VectorTests::UMAXReduceMasked, Short128VectorTests::UMAXReduceAllMasked); + } + static short FIRST_NONZEROReduce(short[] a, int idx) { short res = (short) 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { diff --git a/test/jdk/jdk/incubator/vector/Short256VectorTests.java b/test/jdk/jdk/incubator/vector/Short256VectorTests.java index fa8ec1f31b6..2386d89e53b 100644 --- a/test/jdk/jdk/incubator/vector/Short256VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Short256VectorTests.java @@ -3903,6 +3903,184 @@ static void MAXReduceShort256VectorTestsMasked(IntFunction<short[]> fa, IntFunct Short256VectorTests::MAXReduceMasked, Short256VectorTests::MAXReduceAllMasked); } + static short UMINReduce(short[] a, int idx) { + short res = Short.MAX_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = (short) VectorMath.minUnsigned(res, a[i]); + } + + return res; + } + + static short UMINReduceAll(short[] a) { + short res = Short.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (short) VectorMath.minUnsigned(res, UMINReduce(a, i)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void UMINReduceShort256VectorTests(IntFunction<short[]> fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + short ra = Short.MAX_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMIN); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Short.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + ra = (short) VectorMath.minUnsigned(ra, av.reduceLanes(VectorOperators.UMIN)); + } + } + + assertReductionArraysEquals(r, ra, a, + Short256VectorTests::UMINReduce, Short256VectorTests::UMINReduceAll); + } + + static short UMINReduceMasked(short[] a, int idx, boolean[] mask) { + short res = Short.MAX_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = (short) VectorMath.minUnsigned(res, a[i]); + } + + return res; + } + + static short UMINReduceAllMasked(short[] a, boolean[] mask) { + short res = Short.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (short) VectorMath.minUnsigned(res, UMINReduceMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void UMINReduceShort256VectorTestsMasked(IntFunction<short[]> fa, IntFunction<boolean[]> fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask<Short> vmask = VectorMask.fromArray(SPECIES, mask, 0); + short ra = Short.MAX_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMIN, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Short.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + ra = (short) VectorMath.minUnsigned(ra, av.reduceLanes(VectorOperators.UMIN, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Short256VectorTests::UMINReduceMasked, Short256VectorTests::UMINReduceAllMasked); + } + + static short UMAXReduce(short[] a, int idx) { + short res = Short.MIN_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = (short) VectorMath.maxUnsigned(res, a[i]); + } + + return res; + } + + static short UMAXReduceAll(short[] a) { + short res = Short.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (short) VectorMath.maxUnsigned(res, UMAXReduce(a, i)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void UMAXReduceShort256VectorTests(IntFunction<short[]> fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + short ra = Short.MIN_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMAX); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Short.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + ra = (short) VectorMath.maxUnsigned(ra, av.reduceLanes(VectorOperators.UMAX)); + } + } + + assertReductionArraysEquals(r, ra, a, + Short256VectorTests::UMAXReduce, Short256VectorTests::UMAXReduceAll); + } + + static short UMAXReduceMasked(short[] a, int idx, boolean[] mask) { + short res = Short.MIN_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = (short) VectorMath.maxUnsigned(res, a[i]); + } + + return res; + } + + static short UMAXReduceAllMasked(short[] a, boolean[] mask) { + short res = Short.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (short) VectorMath.maxUnsigned(res, UMAXReduceMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void UMAXReduceShort256VectorTestsMasked(IntFunction<short[]> fa, IntFunction<boolean[]> fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask<Short> vmask = VectorMask.fromArray(SPECIES, mask, 0); + short ra = Short.MIN_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMAX, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Short.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + ra = (short) VectorMath.maxUnsigned(ra, av.reduceLanes(VectorOperators.UMAX, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Short256VectorTests::UMAXReduceMasked, Short256VectorTests::UMAXReduceAllMasked); + } + static short FIRST_NONZEROReduce(short[] a, int idx) { short res = (short) 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { diff --git a/test/jdk/jdk/incubator/vector/Short512VectorTests.java b/test/jdk/jdk/incubator/vector/Short512VectorTests.java index ba6a7dadebd..cb9fc1830b9 100644 --- a/test/jdk/jdk/incubator/vector/Short512VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Short512VectorTests.java @@ -3903,6 +3903,184 @@ static void MAXReduceShort512VectorTestsMasked(IntFunction<short[]> fa, IntFunct Short512VectorTests::MAXReduceMasked, Short512VectorTests::MAXReduceAllMasked); } + static short UMINReduce(short[] a, int idx) { + short res = Short.MAX_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = (short) VectorMath.minUnsigned(res, a[i]); + } + + return res; + } + + static short UMINReduceAll(short[] a) { + short res = Short.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (short) VectorMath.minUnsigned(res, UMINReduce(a, i)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void UMINReduceShort512VectorTests(IntFunction<short[]> fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + short ra = Short.MAX_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMIN); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Short.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + ra = (short) VectorMath.minUnsigned(ra, av.reduceLanes(VectorOperators.UMIN)); + } + } + + assertReductionArraysEquals(r, ra, a, + Short512VectorTests::UMINReduce, Short512VectorTests::UMINReduceAll); + } + + static short UMINReduceMasked(short[] a, int idx, boolean[] mask) { + short res = Short.MAX_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = (short) VectorMath.minUnsigned(res, a[i]); + } + + return res; + } + + static short UMINReduceAllMasked(short[] a, boolean[] mask) { + short res = Short.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (short) VectorMath.minUnsigned(res, UMINReduceMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void UMINReduceShort512VectorTestsMasked(IntFunction<short[]> fa, IntFunction<boolean[]> fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask<Short> vmask = VectorMask.fromArray(SPECIES, mask, 0); + short ra = Short.MAX_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMIN, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Short.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + ra = (short) VectorMath.minUnsigned(ra, av.reduceLanes(VectorOperators.UMIN, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Short512VectorTests::UMINReduceMasked, Short512VectorTests::UMINReduceAllMasked); + } + + static short UMAXReduce(short[] a, int idx) { + short res = Short.MIN_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = (short) VectorMath.maxUnsigned(res, a[i]); + } + + return res; + } + + static short UMAXReduceAll(short[] a) { + short res = Short.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (short) VectorMath.maxUnsigned(res, UMAXReduce(a, i)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void UMAXReduceShort512VectorTests(IntFunction<short[]> fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + short ra = Short.MIN_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMAX); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Short.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + ra = (short) VectorMath.maxUnsigned(ra, av.reduceLanes(VectorOperators.UMAX)); + } + } + + assertReductionArraysEquals(r, ra, a, + Short512VectorTests::UMAXReduce, Short512VectorTests::UMAXReduceAll); + } + + static short UMAXReduceMasked(short[] a, int idx, boolean[] mask) { + short res = Short.MIN_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = (short) VectorMath.maxUnsigned(res, a[i]); + } + + return res; + } + + static short UMAXReduceAllMasked(short[] a, boolean[] mask) { + short res = Short.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (short) VectorMath.maxUnsigned(res, UMAXReduceMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void UMAXReduceShort512VectorTestsMasked(IntFunction<short[]> fa, IntFunction<boolean[]> fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask<Short> vmask = VectorMask.fromArray(SPECIES, mask, 0); + short ra = Short.MIN_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMAX, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Short.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + ra = (short) VectorMath.maxUnsigned(ra, av.reduceLanes(VectorOperators.UMAX, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Short512VectorTests::UMAXReduceMasked, Short512VectorTests::UMAXReduceAllMasked); + } + static short FIRST_NONZEROReduce(short[] a, int idx) { short res = (short) 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { diff --git a/test/jdk/jdk/incubator/vector/Short64VectorTests.java b/test/jdk/jdk/incubator/vector/Short64VectorTests.java index 939da11d53a..64bb5f52329 100644 --- a/test/jdk/jdk/incubator/vector/Short64VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Short64VectorTests.java @@ -3903,6 +3903,184 @@ static void MAXReduceShort64VectorTestsMasked(IntFunction<short[]> fa, IntFuncti Short64VectorTests::MAXReduceMasked, Short64VectorTests::MAXReduceAllMasked); } + static short UMINReduce(short[] a, int idx) { + short res = Short.MAX_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = (short) VectorMath.minUnsigned(res, a[i]); + } + + return res; + } + + static short UMINReduceAll(short[] a) { + short res = Short.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (short) VectorMath.minUnsigned(res, UMINReduce(a, i)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void UMINReduceShort64VectorTests(IntFunction<short[]> fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + short ra = Short.MAX_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMIN); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Short.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + ra = (short) VectorMath.minUnsigned(ra, av.reduceLanes(VectorOperators.UMIN)); + } + } + + assertReductionArraysEquals(r, ra, a, + Short64VectorTests::UMINReduce, Short64VectorTests::UMINReduceAll); + } + + static short UMINReduceMasked(short[] a, int idx, boolean[] mask) { + short res = Short.MAX_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = (short) VectorMath.minUnsigned(res, a[i]); + } + + return res; + } + + static short UMINReduceAllMasked(short[] a, boolean[] mask) { + short res = Short.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (short) VectorMath.minUnsigned(res, UMINReduceMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void UMINReduceShort64VectorTestsMasked(IntFunction<short[]> fa, IntFunction<boolean[]> fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask<Short> vmask = VectorMask.fromArray(SPECIES, mask, 0); + short ra = Short.MAX_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMIN, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Short.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + ra = (short) VectorMath.minUnsigned(ra, av.reduceLanes(VectorOperators.UMIN, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Short64VectorTests::UMINReduceMasked, Short64VectorTests::UMINReduceAllMasked); + } + + static short UMAXReduce(short[] a, int idx) { + short res = Short.MIN_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = (short) VectorMath.maxUnsigned(res, a[i]); + } + + return res; + } + + static short UMAXReduceAll(short[] a) { + short res = Short.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (short) VectorMath.maxUnsigned(res, UMAXReduce(a, i)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void UMAXReduceShort64VectorTests(IntFunction<short[]> fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + short ra = Short.MIN_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMAX); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Short.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + ra = (short) VectorMath.maxUnsigned(ra, av.reduceLanes(VectorOperators.UMAX)); + } + } + + assertReductionArraysEquals(r, ra, a, + Short64VectorTests::UMAXReduce, Short64VectorTests::UMAXReduceAll); + } + + static short UMAXReduceMasked(short[] a, int idx, boolean[] mask) { + short res = Short.MIN_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = (short) VectorMath.maxUnsigned(res, a[i]); + } + + return res; + } + + static short UMAXReduceAllMasked(short[] a, boolean[] mask) { + short res = Short.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (short) VectorMath.maxUnsigned(res, UMAXReduceMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void UMAXReduceShort64VectorTestsMasked(IntFunction<short[]> fa, IntFunction<boolean[]> fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask<Short> vmask = VectorMask.fromArray(SPECIES, mask, 0); + short ra = Short.MIN_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMAX, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Short.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + ra = (short) VectorMath.maxUnsigned(ra, av.reduceLanes(VectorOperators.UMAX, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + Short64VectorTests::UMAXReduceMasked, Short64VectorTests::UMAXReduceAllMasked); + } + static short FIRST_NONZEROReduce(short[] a, int idx) { short res = (short) 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { diff --git a/test/jdk/jdk/incubator/vector/ShortMaxVectorTests.java b/test/jdk/jdk/incubator/vector/ShortMaxVectorTests.java index ade78e1f3f5..6445443b9d6 100644 --- a/test/jdk/jdk/incubator/vector/ShortMaxVectorTests.java +++ b/test/jdk/jdk/incubator/vector/ShortMaxVectorTests.java @@ -3908,6 +3908,184 @@ static void MAXReduceShortMaxVectorTestsMasked(IntFunction<short[]> fa, IntFunct ShortMaxVectorTests::MAXReduceMasked, ShortMaxVectorTests::MAXReduceAllMasked); } + static short UMINReduce(short[] a, int idx) { + short res = Short.MAX_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = (short) VectorMath.minUnsigned(res, a[i]); + } + + return res; + } + + static short UMINReduceAll(short[] a) { + short res = Short.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (short) VectorMath.minUnsigned(res, UMINReduce(a, i)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void UMINReduceShortMaxVectorTests(IntFunction<short[]> fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + short ra = Short.MAX_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMIN); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Short.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + ra = (short) VectorMath.minUnsigned(ra, av.reduceLanes(VectorOperators.UMIN)); + } + } + + assertReductionArraysEquals(r, ra, a, + ShortMaxVectorTests::UMINReduce, ShortMaxVectorTests::UMINReduceAll); + } + + static short UMINReduceMasked(short[] a, int idx, boolean[] mask) { + short res = Short.MAX_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = (short) VectorMath.minUnsigned(res, a[i]); + } + + return res; + } + + static short UMINReduceAllMasked(short[] a, boolean[] mask) { + short res = Short.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (short) VectorMath.minUnsigned(res, UMINReduceMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void UMINReduceShortMaxVectorTestsMasked(IntFunction<short[]> fa, IntFunction<boolean[]> fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask<Short> vmask = VectorMask.fromArray(SPECIES, mask, 0); + short ra = Short.MAX_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMIN, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Short.MAX_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + ra = (short) VectorMath.minUnsigned(ra, av.reduceLanes(VectorOperators.UMIN, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + ShortMaxVectorTests::UMINReduceMasked, ShortMaxVectorTests::UMINReduceAllMasked); + } + + static short UMAXReduce(short[] a, int idx) { + short res = Short.MIN_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + res = (short) VectorMath.maxUnsigned(res, a[i]); + } + + return res; + } + + static short UMAXReduceAll(short[] a) { + short res = Short.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (short) VectorMath.maxUnsigned(res, UMAXReduce(a, i)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpProvider") + static void UMAXReduceShortMaxVectorTests(IntFunction<short[]> fa) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + short ra = Short.MIN_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMAX); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Short.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + ra = (short) VectorMath.maxUnsigned(ra, av.reduceLanes(VectorOperators.UMAX)); + } + } + + assertReductionArraysEquals(r, ra, a, + ShortMaxVectorTests::UMAXReduce, ShortMaxVectorTests::UMAXReduceAll); + } + + static short UMAXReduceMasked(short[] a, int idx, boolean[] mask) { + short res = Short.MIN_VALUE; + for (int i = idx; i < (idx + SPECIES.length()); i++) { + if (mask[i % SPECIES.length()]) + res = (short) VectorMath.maxUnsigned(res, a[i]); + } + + return res; + } + + static short UMAXReduceAllMasked(short[] a, boolean[] mask) { + short res = Short.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + res = (short) VectorMath.maxUnsigned(res, UMAXReduceMasked(a, i, mask)); + } + + return res; + } + + @Test(dataProvider = "shortUnaryOpMaskProvider") + static void UMAXReduceShortMaxVectorTestsMasked(IntFunction<short[]> fa, IntFunction<boolean[]> fm) { + short[] a = fa.apply(SPECIES.length()); + short[] r = fr.apply(SPECIES.length()); + boolean[] mask = fm.apply(SPECIES.length()); + VectorMask<Short> vmask = VectorMask.fromArray(SPECIES, mask, 0); + short ra = Short.MIN_VALUE; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + r[i] = av.reduceLanes(VectorOperators.UMAX, vmask); + } + } + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + ra = Short.MIN_VALUE; + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + ra = (short) VectorMath.maxUnsigned(ra, av.reduceLanes(VectorOperators.UMAX, vmask)); + } + } + + assertReductionArraysEqualsMasked(r, ra, a, mask, + ShortMaxVectorTests::UMAXReduceMasked, ShortMaxVectorTests::UMAXReduceAllMasked); + } + static short FIRST_NONZEROReduce(short[] a, int idx) { short res = (short) 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { diff --git a/test/jdk/jdk/incubator/vector/gen-template.sh b/test/jdk/jdk/incubator/vector/gen-template.sh index 232de04ba7c..06e89b824cd 100644 --- a/test/jdk/jdk/incubator/vector/gen-template.sh +++ b/test/jdk/jdk/incubator/vector/gen-template.sh @@ -484,6 +484,8 @@ gen_reduction_op "ADD" "+" "" "0" gen_reduction_op "MUL" "*" "" "1" gen_reduction_op_func "MIN" "(\$type\$) Math.min" "" "\$Wideboxtype\$.\$MaxValue\$" gen_reduction_op_func "MAX" "(\$type\$) Math.max" "" "\$Wideboxtype\$.\$MinValue\$" +gen_reduction_op_func "UMIN" "(\$type\$) VectorMath.minUnsigned" "BITWISE" "\$Wideboxtype\$.\$MaxValue\$" +gen_reduction_op_func "UMAX" "(\$type\$) VectorMath.maxUnsigned" "BITWISE" "\$Wideboxtype\$.\$MinValue\$" gen_reduction_op_func "FIRST_NONZERO" "firstNonZero" "" "(\$type\$) 0" # Boolean reductions. diff --git a/test/jdk/sun/security/provider/hss/TestHSS.java b/test/jdk/sun/security/provider/hss/TestHSS.java index 0af911f806b..8056855cc1a 100644 --- a/test/jdk/sun/security/provider/hss/TestHSS.java +++ b/test/jdk/sun/security/provider/hss/TestHSS.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 8298127 + * @bug 8298127 8347596 * @library /test/lib * @summary tests for HSS/LMS provider * @modules java.base/sun.security.util @@ -40,6 +40,7 @@ import java.security.spec.X509EncodedKeySpec; import java.util.HexFormat; +import jdk.test.lib.Asserts; import sun.security.util.*; import jdk.test.lib.util.SerializationUtils; @@ -61,9 +62,7 @@ public static void main(String[] args) throws Exception { i++; } - if (!serializeTest()) { - throw new RuntimeException("serializeTest failed"); - } + serializeTest(); System.out.println("All tests passed"); } @@ -88,7 +87,7 @@ static boolean kat(TestCase t) throws Exception { } } - static boolean serializeTest() throws Exception { + static void serializeTest() throws Exception { final ObjectIdentifier oid; var pk = decode(""" 00000002 @@ -106,7 +105,19 @@ static boolean serializeTest() throws Exception { throw new AssertionError(e); } - var keyBits = new DerOutputStream().putOctetString(pk).toByteArray(); + // Encoding without inner OCTET STRING + var pk0 = makeKey(oid, pk); + // Encoding with inner OCTET STRING + var pk1 = makeKey(oid, new DerOutputStream().putOctetString(pk).toByteArray()); + Asserts.assertEquals(pk0, pk1); + + PublicKey pk2 = (PublicKey) SerializationUtils + .deserialize(SerializationUtils.serialize(pk1)); + Asserts.assertEquals(pk1, pk2); + } + + static PublicKey makeKey(ObjectIdentifier oid, byte[] keyBits) + throws Exception { var oidBytes = new DerOutputStream().write(DerValue.tag_Sequence, new DerOutputStream().putOID(oid)); var x509encoding = new DerOutputStream().write(DerValue.tag_Sequence, @@ -115,11 +126,7 @@ static boolean serializeTest() throws Exception { .toByteArray(); var x509KeySpec = new X509EncodedKeySpec(x509encoding); - var pk1 = KeyFactory.getInstance(ALG).generatePublic(x509KeySpec); - - PublicKey pk2 = (PublicKey) SerializationUtils - .deserialize(SerializationUtils.serialize(pk1)); - return pk2.equals(pk1); + return KeyFactory.getInstance(ALG).generatePublic(x509KeySpec); } static boolean verify(byte[] pk, byte[] sig, byte[] msg) throws Exception { diff --git a/test/jdk/sun/security/tools/jarsigner/CheckSignerCertChain.java b/test/jdk/sun/security/tools/jarsigner/CheckSignerCertChain.java index da409612efe..eb3b9395b91 100644 --- a/test/jdk/sun/security/tools/jarsigner/CheckSignerCertChain.java +++ b/test/jdk/sun/security/tools/jarsigner/CheckSignerCertChain.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -81,10 +81,10 @@ public static void main(String[] args) throws Exception { "-sigalg SHA256withRSA " + "-verbose" + " a.jar e1") - .shouldContain("Signature algorithm: SHA1withRSA (disabled), 2048-bit key") + .shouldContain("Signature algorithm: SHA1withRSA (disabled), 2048-bit RSA key") // For trusted cert, warning should be generated for its weak 1024-bit // key, but not for its SHA1withRSA algorithm. - .shouldContain("Signature algorithm: SHA1withRSA, 1024-bit key (weak)") + .shouldContain("Signature algorithm: SHA1withRSA, 1024-bit RSA key (weak)") .shouldHaveExitValue(0); kt("-exportcert -alias ca -rfc -file cacert", "ks"); @@ -92,10 +92,10 @@ public static void main(String[] args) throws Exception { SecurityTools.jarsigner("-verify -certs signeda.jar " + "-keystore caks -storepass changeit -verbose -debug") - .shouldContain("Signature algorithm: SHA1withRSA (disabled), 2048-bit key") + .shouldContain("Signature algorithm: SHA1withRSA (disabled), 2048-bit RSA key") // For trusted cert, warning should be generated for its weak 1024-bit // key, but not for its SHA1withRSA algorithm. - .shouldContain("Signature algorithm: SHA1withRSA, 1024-bit key (weak)") + .shouldContain("Signature algorithm: SHA1withRSA, 1024-bit RSA key (weak)") .shouldHaveExitValue(0); /* @@ -118,8 +118,8 @@ public static void main(String[] args) throws Exception { "-J-Djava.security.properties=" + JAVA_SECURITY_FILE + " a.jar ee") - .shouldNotContain("Signature algorithm: MD5withRSA (disabled), 2048-bit key") - .shouldContain("Signature algorithm: SHA384withRSA, 2048-bit key") + .shouldNotContain("Signature algorithm: MD5withRSA (disabled), 2048-bit RSA key") + .shouldContain("Signature algorithm: SHA384withRSA, 2048-bit RSA key") .shouldNotContain("Invalid certificate chain: Algorithm constraints check failed on signature algorithm: MD5withRSA") .shouldHaveExitValue(0); @@ -134,8 +134,8 @@ public static void main(String[] args) throws Exception { "-J-Djava.security.properties=" + JAVA_SECURITY_FILE + " a.jar ee") - .shouldContain("Signature algorithm: MD5withRSA (disabled), 2048-bit key") - .shouldContain("Signature algorithm: SHA384withRSA, 2048-bit key") + .shouldContain("Signature algorithm: MD5withRSA (disabled), 2048-bit RSA key") + .shouldContain("Signature algorithm: SHA384withRSA, 2048-bit RSA key") .shouldContain("Invalid certificate chain: Algorithm constraints check failed on disabled algorithm: MD5 used with certificate: CN=EE") .shouldHaveExitValue(0); @@ -144,8 +144,8 @@ public static void main(String[] args) throws Exception { SecurityTools.jarsigner("-verify -certs signeda.jar " + "-keystore caks1 -storepass changeit -verbose -debug") - .shouldContain("Signature algorithm: MD5withRSA (disabled), 2048-bit key") - .shouldContain("Signature algorithm: SHA384withRSA, 2048-bit key") + .shouldContain("Signature algorithm: MD5withRSA (disabled), 2048-bit RSA key") + .shouldContain("Signature algorithm: SHA384withRSA, 2048-bit RSA key") .shouldContain("Invalid certificate chain: Algorithm constraints check failed on disabled algorithm: MD5 used with certificate: CN=EE") .shouldHaveExitValue(0); } diff --git a/test/jdk/sun/security/tools/jarsigner/DisableCurveTest.java b/test/jdk/sun/security/tools/jarsigner/DisableCurveTest.java index 353f82ad4b2..ee83c95333c 100644 --- a/test/jdk/sun/security/tools/jarsigner/DisableCurveTest.java +++ b/test/jdk/sun/security/tools/jarsigner/DisableCurveTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -60,7 +60,7 @@ public static void main(String[] args) throws Exception{ .shouldContain(">>> Signer") .shouldContain("Signature algorithm: SHA384withECDSA, 256-bit EC (secp256r1) key (disabled)") .shouldContain("Warning:") - .shouldContain("The EC (secp256r1) signing key has a keysize of 256 which is considered a security risk and is disabled") + .shouldContain("The 256-bit EC (secp256r1) signing key is considered a security risk and is disabled") .shouldHaveExitValue(0); SecurityTools.jarsigner("-verify signeda.jar " + @@ -84,7 +84,7 @@ public static void main(String[] args) throws Exception{ .shouldContain(">>> Signer") .shouldContain("Signature algorithm: SHA384withECDSA, 256-bit EC (secp256r1) key (weak)") .shouldContain("Warning:") - .shouldContain("The EC (secp256r1) signing key has a keysize of 256 which is considered a security risk. This key size will be disabled in a future update") + .shouldContain("The 256-bit EC (secp256r1) signing key is considered a security risk. It will be disabled in a future update") .shouldHaveExitValue(0); SecurityTools.jarsigner("-verify signeda.jar " + @@ -94,7 +94,7 @@ public static void main(String[] args) throws Exception{ .shouldContain("- Signed by") .shouldContain("Signature algorithm: SHA384withECDSA, 256-bit EC (secp256r1) key (weak)") .shouldContain("jar verified") - .shouldContain("The EC (secp256r1) signing key has a keysize of 256 which is considered a security risk. This key size will be disabled in a future update") + .shouldContain("The 256-bit EC (secp256r1) signing key is considered a security risk. It will be disabled in a future update") .shouldHaveExitValue(0); } } diff --git a/test/jdk/sun/security/tools/jarsigner/TimestampCheck.java b/test/jdk/sun/security/tools/jarsigner/TimestampCheck.java index c4cf1ef6a98..bddc8c0e5fb 100644 --- a/test/jdk/sun/security/tools/jarsigner/TimestampCheck.java +++ b/test/jdk/sun/security/tools/jarsigner/TimestampCheck.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -448,8 +448,8 @@ public static void main(String[] args) throws Throwable { .shouldNotContain("The SHA-256 algorithm specified " + "for the -tsadigestalg option is considered a " + "security risk") - .shouldContain("The RSA signing key has a keysize " + - "of 1024 which is considered a security risk") + .shouldContain("The 1024-bit RSA signing key " + + "is considered a security risk") .shouldHaveExitValue(0); checkMultipleWeak("sign2.jar"); diff --git a/test/jdk/sun/security/tools/jarsigner/compatibility/Compatibility.java b/test/jdk/sun/security/tools/jarsigner/compatibility/Compatibility.java index 7fab7d828ae..4a5d595a3c6 100644 --- a/test/jdk/sun/security/tools/jarsigner/compatibility/Compatibility.java +++ b/test/jdk/sun/security/tools/jarsigner/compatibility/Compatibility.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -717,7 +717,8 @@ private static void verifying(SignItem signItem, VerifyItem verifyItem) String match = "^ (" + " Signature algorithm: " + signItem.certInfo. expectedSigalg(signItem) + ", " + signItem.certInfo. - expectedKeySize() + "-bit key" + expectedKeySize() + "-bit " + signItem.certInfo. + expectedKeyAlgorithm() + " key" + ")|(" + " Digest algorithm: " + signItem.expectedDigestAlg() + (isWeakAlg(signItem.expectedDigestAlg()) ? " \\(weak\\)" : "") @@ -1223,6 +1224,12 @@ private String expectedSigalg(SignItem signer) { } } + private String expectedKeyAlgorithm() { + return keyAlgorithm.equals("EC") + ? ("EC .secp" + expectedKeySize() + "r1.") + : keyAlgorithm; + } + private int expectedKeySize() { if (keySize != 0) return keySize; diff --git a/test/jdk/sun/security/tools/jarsigner/warnings/Test.java b/test/jdk/sun/security/tools/jarsigner/warnings/Test.java index 71d4ee144b9..0683c03c10c 100644 --- a/test/jdk/sun/security/tools/jarsigner/warnings/Test.java +++ b/test/jdk/sun/security/tools/jarsigner/warnings/Test.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -149,7 +149,7 @@ public abstract class Test { + "This algorithm will be disabled in a future update."; static final String WEAK_KEY_WARNING - = "This key size will be disabled in a future update."; + = "It will be disabled in a future update."; static final String JAR_SIGNED = "jar signed."; diff --git a/test/jdk/sun/security/tools/keytool/GenKeyPairSigner.java b/test/jdk/sun/security/tools/keytool/GenKeyPairSigner.java index 84cfcd7cb17..113ff2859d5 100644 --- a/test/jdk/sun/security/tools/keytool/GenKeyPairSigner.java +++ b/test/jdk/sun/security/tools/keytool/GenKeyPairSigner.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -77,14 +77,14 @@ static void testSignerPKCS12() throws Exception { SecurityTools.keytool("-keystore ks -storepass changeit " + "-genkeypair -keyalg EdDSA -alias ca -dname CN=CA -ext bc:c " + "-ext 2.5.29.14=04:14:00:01:02:03:04:05:06:07:08:09:10:11:12:13:14:15:16:17:18:19") - .shouldContain("Generating 255 bit Ed25519 key pair and self-signed certificate (Ed25519) with a validity of 90 days") + .shouldContain("Generating Ed25519 key pair and self-signed certificate (Ed25519) with a validity of 90 days") .shouldContain("for: CN=CA") .shouldHaveExitValue(0); System.out.println("Generating an XDH cert with -signer option"); SecurityTools.keytool("-keystore ks -storepass changeit " + "-genkeypair -keyalg XDH -alias e1 -dname CN=E1 -signer ca") - .shouldContain("Generating 255 bit X25519 key pair and a certificate (Ed25519) issued by <ca> with a validity of 90 days") + .shouldContain("Generating X25519 key pair and a certificate (Ed25519) issued by <ca> with a validity of 90 days") .shouldContain("for: CN=E1") .shouldHaveExitValue(0); @@ -118,7 +118,7 @@ static void testSignerPKCS12() throws Exception { .shouldContain("Alias name: e1") .shouldContain("Certificate chain length: 2") .shouldContain("Signature algorithm name: Ed25519") - .shouldContain("Subject Public Key Algorithm: 255-bit X25519 key") + .shouldContain("Subject Public Key Algorithm: X25519 key") .shouldHaveExitValue(0); // check to make sure that cert's AKID is created from the SKID of the signing cert @@ -150,7 +150,7 @@ static void testSignerPKCS12() throws Exception { System.out.println("Generating an X448 cert with -signer option"); SecurityTools.keytool("-keystore ks -storepass changeit " + "-genkeypair -keyalg X448 -alias e2 -dname CN=E2 -sigalg SHA384withRSA -signer ca2") - .shouldContain("Generating 448 bit X448 key pair and a certificate (SHA384withRSA) issued by <ca2> with a validity of 90 days") + .shouldContain("Generating X448 key pair and a certificate (SHA384withRSA) issued by <ca2> with a validity of 90 days") .shouldContain("for: CN=E2") .shouldHaveExitValue(0); @@ -177,7 +177,7 @@ static void testSignerPKCS12() throws Exception { "-list -v") .shouldContain("Alias name: e2") .shouldContain("Signature algorithm name: SHA384withRSA") - .shouldContain("Subject Public Key Algorithm: 448-bit X448 key") + .shouldContain("Subject Public Key Algorithm: X448 key") .shouldHaveExitValue(0); kt("-genkeypair -keyalg DSA -alias ca3 -dname CN=CA3 -ext bc:c ", @@ -186,7 +186,7 @@ static void testSignerPKCS12() throws Exception { System.out.println("Generating a DH cert with -signer option"); SecurityTools.keytool("-keystore ks -storepass changeit " + "-genkeypair -keyalg DH -alias e3 -dname CN=E3 -signer ca3") - .shouldContain("Generating 3,072 bit DH key pair and a certificate (SHA256withDSA) issued by <ca3> with a validity of 90 days") + .shouldContain("Generating 3072-bit DH key pair and a certificate (SHA256withDSA) issued by <ca3> with a validity of 90 days") .shouldContain("for: CN=E3") .shouldHaveExitValue(0); @@ -239,7 +239,7 @@ static void testSignerJKS() throws Exception { SecurityTools.keytool("-keystore ksjks -storepass changeit -storetype jks " + "-genkeypair -keyalg DSA -keysize 1024 -alias ca1 -dname CN=CA1 " + "-keypass ca1keypass -signer ca -signerkeypass cakeypass") - .shouldContain("Generating 1,024 bit DSA key pair and a certificate (SHA384withRSA) issued by <ca> with a validity of 90 days") + .shouldContain("Generating 1024-bit DSA key pair and a certificate (SHA384withRSA) issued by <ca> with a validity of 90 days") .shouldContain("for: CN=CA1") .shouldContain("The generated certificate #1 of 2 uses a 1024-bit DSA key which is considered a security risk") .shouldContain("The generated certificate #2 of 2 uses a 1024-bit RSA key which is considered a security risk") @@ -249,7 +249,7 @@ static void testSignerJKS() throws Exception { SecurityTools.keytool("-keystore ksjks -storepass changeit -storetype jks " + "-genkeypair -keyalg XDH -alias e1 -dname CN=E1 " + "-keypass e1keypass -signer ca1 -signerkeypass ca1keypass") - .shouldContain("Generating 255 bit X25519 key pair and a certificate (SHA256withDSA) issued by <ca1> with a validity of 90 days") + .shouldContain("Generating X25519 key pair and a certificate (SHA256withDSA) issued by <ca1> with a validity of 90 days") .shouldContain("for: CN=E1") .shouldContain("The generated certificate #2 of 3 uses a 1024-bit DSA key which is considered a security risk") .shouldContain("The generated certificate #3 of 3 uses a 1024-bit RSA key which is considered a security risk") @@ -285,7 +285,7 @@ static void testSignerJKS() throws Exception { .shouldContain("Alias name: e1") .shouldContain("Certificate chain length: 3") .shouldContain("Signature algorithm name: SHA256withDSA") - .shouldContain("Subject Public Key Algorithm: 255-bit X25519 key") + .shouldContain("Subject Public Key Algorithm: X25519 key") .shouldHaveExitValue(0); } diff --git a/test/jdk/sun/security/tools/keytool/KeyAlg.java b/test/jdk/sun/security/tools/keytool/KeyAlg.java index ed5061949bf..2fcf2dfb70e 100644 --- a/test/jdk/sun/security/tools/keytool/KeyAlg.java +++ b/test/jdk/sun/security/tools/keytool/KeyAlg.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,9 +42,9 @@ public static void main(String[] args) throws Exception { .shouldMatch("Signature algorithm name:.*SHA1withECDSA") .shouldMatch("Subject Public Key Algorithm:.*1024.*RSA"); keytool("-genkeypair -alias g -dname CN=g -keyalg EC -keysize 256") - .shouldContain("Generating 256 bit EC (secp256r1) key pair"); + .shouldContain("Generating 256-bit EC (secp256r1) key pair"); keytool("-genkeypair -alias f -dname CN=f -keyalg EC") - .shouldContain("Generating 384 bit EC (secp384r1) key pair"); + .shouldContain("Generating 384-bit EC (secp384r1) key pair"); } static OutputAnalyzer keytool(String s) throws Exception { diff --git a/test/jdk/tools/jlink/IntegrationTest.java b/test/jdk/tools/jlink/IntegrationTest.java index d79752f6d56..5a8d0bce15a 100644 --- a/test/jdk/tools/jlink/IntegrationTest.java +++ b/test/jdk/tools/jlink/IntegrationTest.java @@ -154,9 +154,13 @@ private static void test() throws Exception { mods.add("java.management"); Set<String> limits = new HashSet<>(); limits.add("java.management"); + boolean linkFromRuntime = false; JlinkConfiguration config = new Jlink.JlinkConfiguration(output, mods, - JlinkTask.newModuleFinder(modulePaths, limits, mods), false, false, false); + JlinkTask.limitFinder(JlinkTask.newModuleFinder(modulePaths), limits, mods), + linkFromRuntime, + false /* ignore modified runtime */, + false /* generate run-time image */); List<Plugin> lst = new ArrayList<>(); diff --git a/test/jdk/tools/jlink/JLinkTest.java b/test/jdk/tools/jlink/JLinkTest.java index 63863812e2a..d795507cb20 100644 --- a/test/jdk/tools/jlink/JLinkTest.java +++ b/test/jdk/tools/jlink/JLinkTest.java @@ -27,17 +27,15 @@ import java.lang.module.ModuleDescriptor; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.spi.ToolProvider; import java.util.stream.Collectors; import java.util.stream.IntStream; import java.util.stream.Stream; -import jdk.tools.jlink.plugin.Plugin; import jdk.tools.jlink.internal.PluginRepository; +import jdk.tools.jlink.plugin.Plugin; import tests.Helper; import tests.JImageGenerator; @@ -135,11 +133,11 @@ public static void main(String[] args) throws Exception { { // No --module-path specified. --add-modules ALL-MODULE-PATH specified. - String imageDir = "bug8189777-all-module-path"; + String imageDir = "bug8345259-all-module-path"; JImageGenerator.getJLinkTask() .output(helper.createNewImageDir(imageDir)) .addMods("ALL-MODULE-PATH") - .call().assertSuccess(); + .call().assertFailure(); } { diff --git a/test/jdk/tools/jlink/basic/AllModulePath.java b/test/jdk/tools/jlink/basic/AllModulePath.java index ba6cc08bd47..a05f2d06d86 100644 --- a/test/jdk/tools/jlink/basic/AllModulePath.java +++ b/test/jdk/tools/jlink/basic/AllModulePath.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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,45 +21,52 @@ * questions. */ -/* - * @test - * @summary jlink test of --add-module ALL-MODULE-PATH - * @library /test/lib - * @modules jdk.compiler - * @build jdk.test.lib.process.ProcessTools - * jdk.test.lib.process.OutputAnalyzer - * jdk.test.lib.compiler.CompilerUtils - * @run testng AllModulePath - */ +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; -import java.io.File; +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.PrintWriter; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayList; -import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; -import java.util.stream.Collectors; -import java.util.stream.Stream; import java.util.spi.ToolProvider; - -import jdk.test.lib.compiler.CompilerUtils; -import jdk.test.lib.process.ProcessTools; +import java.util.stream.Collectors; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; -import static org.testng.Assert.*; +import jdk.test.lib.compiler.CompilerUtils; +import jdk.test.lib.process.ProcessTools; +import jdk.tools.jlink.internal.LinkableRuntimeImage; +import tests.Helper; +import tests.Result; + +/* + * @test + * @bug 8345259 + * @summary jlink test of --add-module ALL-MODULE-PATH + * @library ../../lib /test/lib + * @modules jdk.compiler + * java.base/jdk.internal.jimage + * jdk.jlink/jdk.tools.jlink.internal + * jdk.jlink/jdk.tools.jimage + * @build jdk.test.lib.process.ProcessTools + * jdk.test.lib.process.OutputAnalyzer + * jdk.test.lib.compiler.CompilerUtils + * @run testng/othervm -Duser.language=en -Duser.country=US AllModulePath + */ public class AllModulePath { - private final Path JMODS = Paths.get(System.getProperty("test.jdk")).resolve("jmods"); - private final Path SRC = Paths.get(System.getProperty("test.src")).resolve("src"); - private final Path MODS = Paths.get("mods"); + private static final Path JMODS = Paths.get(System.getProperty("test.jdk")).resolve("jmods"); + private static final Path SRC = Paths.get(System.getProperty("test.src")).resolve("src"); + private static final Path MODS = Paths.get("mods"); + private static final boolean LINKABLE_RUNTIME = LinkableRuntimeImage.isLinkableRuntime(); + private static final boolean JMODS_EXIST = Files.exists(JMODS); private final static Set<String> MODULES = Set.of("test", "m1"); @@ -67,12 +74,22 @@ public class AllModulePath { .orElseThrow(() -> new RuntimeException("jlink tool not found") ); + private static Helper HELPER; + + private static boolean isExplodedJDKImage() { + if (!JMODS_EXIST && !LINKABLE_RUNTIME) { + System.err.println("Test skipped. Not a linkable runtime and no JMODs"); + return true; + } + return false; + } @BeforeClass public void setup() throws Throwable { - if (Files.notExists(JMODS)) { + if (isExplodedJDKImage()) { return; } + HELPER = Helper.newHelper(LINKABLE_RUNTIME); Files.createDirectories(MODS); @@ -84,60 +101,114 @@ public void setup() throws Throwable { } } + /* + * --add-modules ALL-MODULE-PATH with an existing module-path. + */ @Test public void testAllModulePath() throws Throwable { - if (Files.notExists(JMODS)) { + if (isExplodedJDKImage()) { return; } - // create custom image - Path image = Paths.get("image"); - createImage(image, "--add-modules", "ALL-MODULE-PATH"); + Path image = HELPER.createNewImageDir("image"); + List<String> opts = List.of("--module-path", MODS.toString(), + "--output", image.toString(), + "--add-modules", "ALL-MODULE-PATH"); + createImage(image, opts, true /* success */); Set<String> modules = new HashSet<>(); - Files.find(JMODS, 1, (Path p, BasicFileAttributes attr) -> - p.toString().endsWith(".jmod")) - .map(p -> JMODS.relativize(p).toString()) - .map(n -> n.substring(0, n.length()-5)) - .forEach(modules::add); + // java.base is a dependency of any external module + modules.add("java.base"); modules.add("m1"); modules.add("test"); checkModules(image, modules); } + /* + * --add-modules ALL-MODULE-PATH with --limit-modules is an error + */ @Test public void testLimitModules() throws Throwable { - if (Files.notExists(JMODS)) { + if (isExplodedJDKImage()) { return; } - - // create custom image - Path image = Paths.get("image1"); - createImage(image, - "--add-modules", "ALL-MODULE-PATH", - "--limit-modules", "m1"); - - checkModules(image, Set.of("m1", "java.base")); + Path targetPath = HELPER.createNewImageDir("all-mods-limit-mods"); + String moduleName = "com.baz.runtime"; + Result result = HELPER.generateDefaultJModule(moduleName, "jdk.jfr"); + Path customModulePath = result.getFile().getParent(); + List<String> allArgs = List.of("--add-modules", "ALL-MODULE-PATH", + "--limit-modules", "jdk.jfr", + "--module-path", customModulePath.toString(), + "--output", targetPath.toString()); + JlinkOutput allOut = createImage(targetPath, allArgs, false /* success */); + String actual = allOut.stdout.trim(); + String expected = "Error: --limit-modules not allowed with --add-modules ALL-MODULE-PATH"; + assertEquals(actual, expected); } + + /* + * --add-modules *includes* ALL-MODULE-PATH with an existing module path + */ @Test public void testAddModules() throws Throwable { - if (Files.notExists(JMODS)) { + if (isExplodedJDKImage()) { return; } // create custom image - Path image = Paths.get("image2"); - createImage(image, - "--add-modules", "m1,test", - "--add-modules", "ALL-MODULE-PATH", - "--limit-modules", "java.base"); + Path image = HELPER.createNewImageDir("image2"); + List<String> opts = List.of("--module-path", MODS.toString(), + "--output", image.toString(), + "--add-modules", "m1", + "--add-modules", "ALL-MODULE-PATH"); + createImage(image, opts, true /* success */); checkModules(image, Set.of("m1", "test", "java.base")); } /* - * check the modules linked in the image + * No --module-path with --add-modules ALL-MODULE-PATH is an error. + */ + @Test + public void noModulePath() throws IOException { + if (isExplodedJDKImage()) { + return; + } + Path targetPath = HELPER.createNewImageDir("all-mod-path-no-mod-path"); + List<String> allArgs = List.of("--add-modules", "ALL-MODULE-PATH", + "--output", targetPath.toString()); + JlinkOutput allOut = createImage(targetPath, allArgs, false /* expect failure */); + String expected = "Error: --module-path option must be specified with --add-modules ALL-MODULE-PATH"; + assertEquals(allOut.stdout.trim(), expected); + } + + /* + * --module-path not-exist and --add-modules ALL-MODULE-PATH is an error. + */ + @Test + public void modulePathEmpty() throws IOException { + if (isExplodedJDKImage()) { + return; + } + Path targetPath = HELPER.createNewImageDir("all-mod-path-not-existing"); + String strNotExists = "not-exist"; + Path notExists = Path.of(strNotExists); + if (Files.exists(notExists)) { + throw new AssertionError("Test setup error, path must not exist!"); + } + List<String> allArgs = List.of("--add-modules", "ALL-MODULE-PATH", + "--module-path", notExists.toString(), + "--output", targetPath.toString()); + + JlinkOutput allOut = createImage(targetPath, allArgs, false /* expect failure */); + String actual = allOut.stdout.trim(); + assertTrue(actual.startsWith("Error: No module found in module path")); + assertTrue(actual.contains(strNotExists)); + } + + /* + * check the modules linked in the image using m1/p.ListModules */ private void checkModules(Path image, Set<String> modules) throws Throwable { Path cmd = findTool(image, "java"); @@ -164,16 +235,19 @@ private Path findTool(Path image, String tool) { return cmd; } - private void createImage(Path image, String... options) throws IOException { - String modulepath = JMODS.toString() + File.pathSeparator + MODS.toString(); - List<String> opts = List.of("--module-path", modulepath, - "--output", image.toString()); - String[] args = Stream.concat(opts.stream(), Arrays.stream(options)) - .toArray(String[]::new); - - System.out.println("jlink " + Arrays.stream(args).collect(Collectors.joining(" "))); - PrintWriter pw = new PrintWriter(System.out); - int rc = JLINK_TOOL.run(pw, pw, args); - assertTrue(rc == 0); + private JlinkOutput createImage(Path image, List<String> args, boolean success) throws IOException { + System.out.println("jlink " + args.stream().collect(Collectors.joining(" "))); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + PrintWriter out = new PrintWriter(baos); + ByteArrayOutputStream berrOs = new ByteArrayOutputStream(); + PrintWriter err = new PrintWriter(berrOs); + int rc = JLINK_TOOL.run(out, err, args.toArray(String[]::new)); + String stdOut = new String(baos.toByteArray()); + String stdErr = new String(berrOs.toByteArray()); + assertEquals(rc == 0, success, String.format("Output was: %nstdout: %s%nstderr: %s%n", stdOut, stdErr)); + return new JlinkOutput(stdErr, stdOut); } + + private static record JlinkOutput(String stderr, String stdout) {}; } diff --git a/test/jdk/tools/jlink/basic/BasicTest.java b/test/jdk/tools/jlink/basic/BasicTest.java index a771d4d0002..1a14e620fa6 100644 --- a/test/jdk/tools/jlink/basic/BasicTest.java +++ b/test/jdk/tools/jlink/basic/BasicTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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,21 +21,6 @@ * questions. */ -/* - * @test - * @summary Basic test of jlink to create jmods and images - * @author Andrei Eremeev - * @library /test/lib - * @modules java.base/jdk.internal.module - * jdk.jlink - * jdk.compiler - * @build jdk.test.lib.process.ProcessTools - * jdk.test.lib.process.OutputAnalyzer - * jdk.test.lib.compiler.CompilerUtils - * jdk.test.lib.util.JarUtils - * @run main BasicTest - */ - import java.io.File; import java.io.PrintWriter; import java.nio.file.Files; @@ -50,7 +35,22 @@ import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.process.ProcessTools; import jdk.test.lib.util.JarUtils; +import jdk.tools.jlink.internal.LinkableRuntimeImage; +/* + * @test + * @summary Basic test of jlink to create jmods and images + * @author Andrei Eremeev + * @library /test/lib + * @modules java.base/jdk.internal.module + * jdk.jlink/jdk.tools.jlink.internal + * jdk.compiler + * @build jdk.test.lib.process.ProcessTools + * jdk.test.lib.process.OutputAnalyzer + * jdk.test.lib.compiler.CompilerUtils + * jdk.test.lib.util.JarUtils + * @run main/othervm BasicTest + */ public class BasicTest { static final ToolProvider JMOD_TOOL = ToolProvider.findFirst("jmod") .orElseThrow(() -> @@ -62,21 +62,31 @@ public class BasicTest { new RuntimeException("jlink tool not found") ); - private final String TEST_MODULE = "test"; - private final Path jdkHome = Paths.get(System.getProperty("test.jdk")); - private final Path jdkMods = jdkHome.resolve("jmods"); - private final Path testSrc = Paths.get(System.getProperty("test.src")); - private final Path src = testSrc.resolve("src").resolve(TEST_MODULE); - private final Path classes = Paths.get("classes"); - private final Path jmods = Paths.get("jmods"); - private final Path jars = Paths.get("jars"); + private static final String TEST_MODULE = "test"; + private static final Path jdkHome = Paths.get(System.getProperty("test.jdk")); + private static final Path jdkMods = jdkHome.resolve("jmods"); + private static final boolean JMODS_EXIST = Files.exists(jdkMods); + private static final boolean LINKABLE_RUNTIME = LinkableRuntimeImage.isLinkableRuntime(); + private static final Path testSrc = Paths.get(System.getProperty("test.src")); + private static final Path src = testSrc.resolve("src").resolve(TEST_MODULE); + private static final Path classes = Paths.get("classes"); + private static final Path jmods = Paths.get("jmods"); + private static final Path jars = Paths.get("jars"); public static void main(String[] args) throws Throwable { new BasicTest().run(); } + private static boolean isExplodedJDKImage() { + if (!JMODS_EXIST && !LINKABLE_RUNTIME) { + System.err.println("Test skipped. Not a linkable runtime and no JMODs"); + return true; + } + return false; + } + public void run() throws Throwable { - if (Files.notExists(jdkMods)) { + if (isExplodedJDKImage()) { return; } @@ -146,8 +156,10 @@ private void execute(Path image, String scriptName) throws Throwable { private void runJlink(Path image, String modName, String... options) { List<String> args = new ArrayList<>(); + String modPathArg = (JMODS_EXIST ? jdkMods + File.pathSeparator : "") + + jmods; Collections.addAll(args, - "--module-path", jdkMods + File.pathSeparator + jmods, + "--module-path", modPathArg, "--add-modules", modName, "--output", image.toString()); Collections.addAll(args, options); diff --git a/test/jdk/tools/jlink/bindservices/BindServices.java b/test/jdk/tools/jlink/bindservices/BindServices.java index 02f8bfd52d2..89095631040 100644 --- a/test/jdk/tools/jlink/bindservices/BindServices.java +++ b/test/jdk/tools/jlink/bindservices/BindServices.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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,6 +21,9 @@ * questions. */ +import static jdk.test.lib.process.ProcessTools.executeProcess; +import static org.testng.Assert.assertTrue; + import java.io.File; import java.io.PrintWriter; import java.io.StringWriter; @@ -33,21 +36,20 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -import jdk.test.lib.compiler.CompilerUtils; -import static jdk.test.lib.process.ProcessTools.*; - import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; -import static org.testng.Assert.*; + +import jdk.test.lib.compiler.CompilerUtils; +import jdk.tools.jlink.internal.LinkableRuntimeImage; /** * @test - * @bug 8174826 + * @bug 8174826 8345573 * @library /test/lib - * @modules jdk.compiler jdk.jlink + * @modules jdk.compiler jdk.jlink/jdk.tools.jlink.internal * @build BindServices jdk.test.lib.process.ProcessTools * jdk.test.lib.compiler.CompilerUtils - * @run testng BindServices + * @run testng/othervm BindServices */ public class BindServices { @@ -56,21 +58,23 @@ public class BindServices { private static final Path SRC_DIR = Paths.get(TEST_SRC, "src"); private static final Path MODS_DIR = Paths.get("mods"); + private static final boolean LINKABLE_RUNTIME = LinkableRuntimeImage.isLinkableRuntime(); + private static final boolean JMODS_EXIST = Files.exists(Paths.get(JAVA_HOME, "jmods")); - private static final String MODULE_PATH = - Paths.get(JAVA_HOME, "jmods").toString() + - File.pathSeparator + MODS_DIR.toString(); + private static final String MODULE_PATH = (JMODS_EXIST ? Paths.get(JAVA_HOME, "jmods").toString() + + File.pathSeparator : "") + + MODS_DIR.toString(); // the names of the modules in this test private static String[] modules = new String[] {"m1", "m2", "m3"}; - private static boolean hasJmods() { - if (!Files.exists(Paths.get(JAVA_HOME, "jmods"))) { - System.err.println("Test skipped. NO jmods directory"); - return false; + private static boolean isExplodedJDKImage() { + if (!JMODS_EXIST && !LINKABLE_RUNTIME) { + System.err.println("Test skipped. Not a linkable runtime and no JMODs"); + return true; } - return true; + return false; } /* @@ -78,7 +82,7 @@ private static boolean hasJmods() { */ @BeforeTest public void compileAll() throws Throwable { - if (!hasJmods()) return; + if (isExplodedJDKImage()) return; for (String mn : modules) { Path msrc = SRC_DIR.resolve(mn); @@ -89,7 +93,7 @@ public void compileAll() throws Throwable { @Test public void noServiceBinding() throws Throwable { - if (!hasJmods()) return; + if (isExplodedJDKImage()) return; Path dir = Paths.get("noServiceBinding"); @@ -103,7 +107,7 @@ public void noServiceBinding() throws Throwable { @Test public void fullServiceBinding() throws Throwable { - if (!hasJmods()) return; + if (isExplodedJDKImage()) return; Path dir = Paths.get("fullServiceBinding"); @@ -122,7 +126,7 @@ public void fullServiceBinding() throws Throwable { @Test public void testVerbose() throws Throwable { - if (!hasJmods()) return; + if (isExplodedJDKImage()) return; Path dir = Paths.get("verbose"); @@ -153,7 +157,7 @@ public void testVerbose() throws Throwable { @Test public void testVerboseAndNoBindServices() throws Throwable { - if (!hasJmods()) return; + if (isExplodedJDKImage()) return; Path dir = Paths.get("verboseNoBind"); diff --git a/test/jdk/tools/jlink/bindservices/SuggestProviders.java b/test/jdk/tools/jlink/bindservices/SuggestProviders.java index 9685f927f8d..794d22fc570 100644 --- a/test/jdk/tools/jlink/bindservices/SuggestProviders.java +++ b/test/jdk/tools/jlink/bindservices/SuggestProviders.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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,6 +21,9 @@ * questions. */ +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; + import java.io.File; import java.io.PrintWriter; import java.io.StringWriter; @@ -32,17 +35,18 @@ import java.util.spi.ToolProvider; import java.util.stream.Collectors; import java.util.stream.Stream; -import jdk.test.lib.compiler.CompilerUtils; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; -import static org.testng.Assert.*; + +import jdk.test.lib.compiler.CompilerUtils; +import jdk.tools.jlink.internal.LinkableRuntimeImage; /** * @test - * @bug 8174826 + * @bug 8174826 8345573 * @library /lib/testlibrary /test/lib - * @modules jdk.charsets jdk.compiler jdk.jlink + * @modules jdk.charsets jdk.compiler jdk.jlink/jdk.tools.jlink.internal * @build SuggestProviders jdk.test.lib.compiler.CompilerUtils * @run testng SuggestProviders */ @@ -54,20 +58,23 @@ public class SuggestProviders { private static final Path SRC_DIR = Paths.get(TEST_SRC, "src"); private static final Path MODS_DIR = Paths.get("mods"); - private static final String MODULE_PATH = - Paths.get(JAVA_HOME, "jmods").toString() + - File.pathSeparator + MODS_DIR.toString(); + private static final boolean LINKABLE_RUNTIME = LinkableRuntimeImage.isLinkableRuntime(); + private static final boolean JMODS_EXIST = Files.exists(Paths.get(JAVA_HOME, "jmods")); + + private static final String MODULE_PATH = (JMODS_EXIST ? Paths.get(JAVA_HOME, "jmods").toString() + + File.pathSeparator : "") + + MODS_DIR.toString(); // the names of the modules in this test private static String[] modules = new String[] {"m1", "m2", "m3"}; - private static boolean hasJmods() { - if (!Files.exists(Paths.get(JAVA_HOME, "jmods"))) { - System.err.println("Test skipped. NO jmods directory"); - return false; + private static boolean isExplodedJDKImage() { + if (!JMODS_EXIST && !LINKABLE_RUNTIME) { + System.err.println("Test skipped. Not a linkable runtime and no JMODs"); + return true; } - return true; + return false; } /* @@ -75,7 +82,7 @@ private static boolean hasJmods() { */ @BeforeTest public void compileAll() throws Throwable { - if (!hasJmods()) return; + if (isExplodedJDKImage()) return; for (String mn : modules) { Path msrc = SRC_DIR.resolve(mn); @@ -125,7 +132,7 @@ public void compileAll() throws Throwable { @Test public void suggestProviders() throws Throwable { - if (!hasJmods()) return; + if (isExplodedJDKImage()) return; List<String> output = JLink.run("--module-path", MODULE_PATH, "--suggest-providers").output(); @@ -145,7 +152,7 @@ public void suggestProviders() throws Throwable { */ @Test public void observableModules() throws Throwable { - if (!hasJmods()) return; + if (isExplodedJDKImage()) return; List<String> output = JLink.run("--module-path", MODULE_PATH, "--add-modules", "m1", @@ -165,7 +172,7 @@ public void observableModules() throws Throwable { */ @Test public void limitModules() throws Throwable { - if (!hasJmods()) return; + if (isExplodedJDKImage()) return; List<String> output = JLink.run("--module-path", MODULE_PATH, "--limit-modules", "m1", @@ -184,7 +191,7 @@ public void limitModules() throws Throwable { @Test public void providersForServices() throws Throwable { - if (!hasJmods()) return; + if (isExplodedJDKImage()) return; List<String> output = JLink.run("--module-path", MODULE_PATH, @@ -203,7 +210,7 @@ public void providersForServices() throws Throwable { @Test public void unusedService() throws Throwable { - if (!hasJmods()) return; + if (isExplodedJDKImage()) return; List<String> output = JLink.run("--module-path", MODULE_PATH, @@ -221,7 +228,7 @@ public void unusedService() throws Throwable { @Test public void nonExistentService() throws Throwable { - if (!hasJmods()) return; + if (isExplodedJDKImage()) return; List<String> output = JLink.run("--module-path", MODULE_PATH, @@ -236,7 +243,7 @@ public void nonExistentService() throws Throwable { @Test public void noSuggestProviders() throws Throwable { - if (!hasJmods()) return; + if (isExplodedJDKImage()) return; List<String> output = JLink.run("--module-path", MODULE_PATH, @@ -250,7 +257,7 @@ public void noSuggestProviders() throws Throwable { @Test public void suggestTypeNotRealProvider() throws Throwable { - if (!hasJmods()) return; + if (isExplodedJDKImage()) return; List<String> output = JLink.run("--module-path", MODULE_PATH, @@ -268,7 +275,7 @@ public void suggestTypeNotRealProvider() throws Throwable { @Test public void addNonObservableModule() throws Throwable { - if (!hasJmods()) return; + if (isExplodedJDKImage()) return; List<String> output = JLink.run("--module-path", MODULE_PATH, diff --git a/test/jdk/tools/jlink/runtimeImage/AbstractLinkableRuntimeTest.java b/test/jdk/tools/jlink/runtimeImage/AbstractLinkableRuntimeTest.java index e7d5340e3b0..1df4455bc7d 100644 --- a/test/jdk/tools/jlink/runtimeImage/AbstractLinkableRuntimeTest.java +++ b/test/jdk/tools/jlink/runtimeImage/AbstractLinkableRuntimeTest.java @@ -192,7 +192,8 @@ protected Path jlinkUsingImage(JlinkSpec spec, OutputAnalyzerHandler handler, Pr // if the exit checker failed, we expected the other outcome // i.e. fail for success and success for fail. boolean successExit = analyzer.getExitValue() == 0; - String msg = String.format("Expected jlink to %s given a jmodless image. Exit code was: %d", + String msg = String.format("Expected jlink to %s given a linkable run-time image. " + + "Exit code was: %d", (successExit ? "fail" : "pass"), analyzer.getExitValue()); throw new AssertionError(msg); } diff --git a/test/jdk/tools/jpackage/share/RuntimeImageSymbolicLinksTest.java b/test/jdk/tools/jpackage/share/RuntimeImageSymbolicLinksTest.java index 404cd3b6d3a..db74e3456c4 100644 --- a/test/jdk/tools/jpackage/share/RuntimeImageSymbolicLinksTest.java +++ b/test/jdk/tools/jpackage/share/RuntimeImageSymbolicLinksTest.java @@ -51,6 +51,7 @@ public class RuntimeImageSymbolicLinksTest { @Test public static void test() throws Exception { + final Path jmods = Path.of(System.getProperty("java.home"), "jmods"); final Path workDir = TKit.createTempDirectory("runtime").resolve("data"); final Path jlinkOutputDir = workDir.resolve("temp.runtime"); Files.createDirectories(jlinkOutputDir.getParent()); @@ -61,6 +62,7 @@ public static void test() throws Exception { .addArguments( "--output", jlinkOutputDir.toString(), "--add-modules", "ALL-MODULE-PATH", + "--module-path", jmods.toString(), "--strip-debug", "--no-header-files", "--no-man-pages", diff --git a/test/jdk/tools/jpackage/share/RuntimeImageTest.java b/test/jdk/tools/jpackage/share/RuntimeImageTest.java index f3751c9ee47..65e8c448d39 100644 --- a/test/jdk/tools/jpackage/share/RuntimeImageTest.java +++ b/test/jdk/tools/jpackage/share/RuntimeImageTest.java @@ -44,6 +44,7 @@ public class RuntimeImageTest { @Test public static void test() throws Exception { + final Path jmods = Path.of(System.getProperty("java.home"), "jmods"); final Path workDir = TKit.createTempDirectory("runtime").resolve("data"); final Path jlinkOutputDir = workDir.resolve("temp.runtime"); Files.createDirectories(jlinkOutputDir.getParent()); @@ -54,6 +55,7 @@ public static void test() throws Exception { .addArguments( "--output", jlinkOutputDir.toString(), "--add-modules", "ALL-MODULE-PATH", + "--module-path", jmods.toString(), "--strip-debug", "--no-header-files", "--no-man-pages", diff --git a/test/jdk/tools/jpackage/share/RuntimePackageTest.java b/test/jdk/tools/jpackage/share/RuntimePackageTest.java index 0b505babcc5..73f1c525654 100644 --- a/test/jdk/tools/jpackage/share/RuntimePackageTest.java +++ b/test/jdk/tools/jpackage/share/RuntimePackageTest.java @@ -101,6 +101,8 @@ private static PackageTest init(Set<PackageType> types) { .forTypes(types) .addInitializer(cmd -> { final Path runtimeImageDir; + final Path jmods = Path.of(System.getProperty("java.home"), "jmods"); + if (JPackageCommand.DEFAULT_RUNTIME_IMAGE != null) { runtimeImageDir = JPackageCommand.DEFAULT_RUNTIME_IMAGE; } else { @@ -112,6 +114,7 @@ private static PackageTest init(Set<PackageType> types) { .addArguments( "--output", runtimeImageDir.toString(), "--add-modules", "ALL-MODULE-PATH", + "--module-path", jmods.toString(), "--strip-debug", "--no-header-files", "--no-man-pages") diff --git a/test/jdk/tools/jpackage/windows/WinLongPathTest.java b/test/jdk/tools/jpackage/windows/WinLongPathTest.java index e9e5ef8ce03..10e713f02a8 100644 --- a/test/jdk/tools/jpackage/windows/WinLongPathTest.java +++ b/test/jdk/tools/jpackage/windows/WinLongPathTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,7 @@ import jdk.jpackage.test.PackageTest; import jdk.jpackage.test.PackageType; import jdk.jpackage.test.Annotations.Test; +import jdk.jpackage.test.Executor; import jdk.jpackage.test.JPackageCommand; import jdk.jpackage.test.RunnablePackageTest.Action; import jdk.jpackage.test.TKit; @@ -39,8 +40,10 @@ * @bug 8289771 * @summary jpackage with long paths on windows * @library /test/jdk/tools/jpackage/helpers + * @library /test/lib * @key jpackagePlatformPackage * @build jdk.jpackage.test.* + * @build jtreg.SkippedException * @requires (os.family == "windows") * @compile WinLongPathTest.java * @run main/othervm/timeout=540 -Xmx512m jdk.jpackage.test.Main @@ -64,6 +67,8 @@ public static List<Object[]> input() { @Test public void test() throws IOException { + verifyDosNamesSupported(); + if (appImage) { var cmd = JPackageCommand.helloAppImage(); setOptionLongPath(cmd, optionName); @@ -84,4 +89,23 @@ private static void setOptionLongPath(JPackageCommand cmd, String option) throws Files.createDirectories(longPath); cmd.setArgumentValue(option, longPath); } + + private static void verifyDosNamesSupported() throws IOException { + // Pick the file's name long enough to make Windows shorten it. + final var probeDosNameFile = TKit.createTempFile(Path.of("probeDosName")); + + // The output should be a DOS variant of the `probeDosNameFile` path. + // The filename should differ if the volume owning `probeDosNameFile` file supports DOS names. + final var dosPath = new Executor() + .addArguments("/c", String.format("for %%P in (\"%s\") do @echo %%~sP", probeDosNameFile)) + .setExecutable("cmd") + .dumpOutput() + .executeAndGetFirstLineOfOutput(); + + if (Path.of(dosPath).getFileName().equals(probeDosNameFile.getFileName())) { + TKit.throwSkippedException(String.format("The volume %s owning the test work directory doesn't support DOS paths", + probeDosNameFile.toAbsolutePath().getRoot())); + } + } + } diff --git a/test/langtools/tools/javac/ImportModule.java b/test/langtools/tools/javac/ImportModule.java index 1224a9d7470..a53bc92f1b0 100644 --- a/test/langtools/tools/javac/ImportModule.java +++ b/test/langtools/tools/javac/ImportModule.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /** * @test - * @bug 8328481 8332236 8332890 + * @bug 8328481 8332236 8332890 8344647 8347646 * @summary Check behavior of module imports. * @library /tools/lib * @modules java.logging @@ -33,12 +33,13 @@ * jdk.compiler/com.sun.tools.javac.util * @build toolbox.ToolBox toolbox.JavacTask * @run main ImportModule -*/ + */ import com.sun.source.tree.Tree; import com.sun.source.util.TaskEvent; import com.sun.source.util.TaskEvent.Kind; import com.sun.source.util.TaskListener; +import java.lang.classfile.ClassFile; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -829,6 +830,7 @@ public class Test { } } + @Test public void testPackageImportDisambiguates(Path base) throws Exception { Path current = base.resolve("."); Path src = current.resolve("src"); @@ -919,4 +921,130 @@ public class Test { .run(Task.Expect.SUCCESS) .writeAll(); } + + @Test //JDK-8344647 + public void testJavaBaseOverride(Path base) throws Exception { + Path current = base.resolve("."); + Path src = current.resolve("src"); + Path javaBaseClasses = current.resolve("javaBaseClasses"); + Path javaBase = src.resolve("java.base"); + tb.writeJavaFiles(javaBase, + """ + module java.base { + exports java.lang; + } + """, + """ + package java.lang; + public class Object {} + """); + + Files.createDirectories(javaBaseClasses); + + new JavacTask(tb) + .options("--patch-module", "java.base=" + src.toString()) + .outdir(javaBaseClasses) + .files(tb.findJavaFiles(src)) + .run(Task.Expect.SUCCESS) + .writeAll() + .getOutputLines(Task.OutputKind.DIRECT); + + Path test = current.resolve("test"); + tb.writeJavaFiles(test, + """ + module test { + requires java.se; + } + """); + + Path classes = current.resolve("classes"); + Files.createDirectories(classes); + + new JavacTask(tb) + .options("--patch-module", "java.base=" + javaBaseClasses.toString()) + .outdir(classes) + .files(tb.findJavaFiles(test)) + .run(Task.Expect.SUCCESS) + .writeAll(); + } + + @Test //JDK-8347646 + public void testRequiresTransitiveJavaBase(Path base) throws Exception { + Path current = base.resolve("."); + Path src = current.resolve("src"); + Path classes = current.resolve("classes"); + Path ma = src.resolve("ma"); + Path maClasses = classes.resolve("ma"); + tb.writeJavaFiles(ma, + """ + module ma { + requires transitive java.base; + } + """); + Path test = src.resolve("test"); + tb.writeJavaFiles(test, + """ + module test { + requires ma; + } + """, + """ + package test; + import module ma; + public class Test { + public static void main(String... args) { + System.out.println(List.of("Hello")); + } + } + """); + + Files.createDirectories(maClasses); + + List<String> actualErrors = new JavacTask(tb) + .options("-XDrawDiagnostics") + .outdir(maClasses) + .files(tb.findJavaFiles(ma)) + .run(Task.Expect.FAIL) + .writeAll() + .getOutputLines(Task.OutputKind.DIRECT); + + List<String> expectedErrors = List.of( + "module-info.java:2:4: compiler.err.preview.feature.disabled.plural: (compiler.misc.feature.java.base.transitive)", + "1 error" + ); + + if (!Objects.equals(expectedErrors, actualErrors)) { + throw new AssertionError("Incorrect Output, expected: " + expectedErrors + + ", actual: " + actualErrors); + + } + + new JavacTask(tb) + .options("-XDrawDiagnostics", + "--source", "9") + .outdir(maClasses) + .files(tb.findJavaFiles(ma)) + .run() + .writeAll(); + + Path maModuleInfo = maClasses.resolve("module-info.class"); + + if (ClassFile.of().parse(maModuleInfo).minorVersion() == ClassFile.PREVIEW_MINOR_VERSION) { + throw new AssertionError("wrong minor version"); + } + + new JavacTask(tb) + .options("-XDrawDiagnostics", + "--enable-preview", "--release", SOURCE_VERSION) + .outdir(maClasses) + .files(tb.findJavaFiles(ma)) + .run() + .writeAll(); + + Path maModuleInfo2 = maClasses.resolve("module-info.class"); + + if (ClassFile.of().parse(maModuleInfo2).minorVersion() != ClassFile.PREVIEW_MINOR_VERSION) { + throw new AssertionError("wrong minor version"); + } + } } diff --git a/test/langtools/tools/javac/LocalFreeVarStaticInstantiate.java b/test/langtools/tools/javac/LocalFreeVarStaticInstantiate.java index 39b419c694a..09d33573da5 100644 --- a/test/langtools/tools/javac/LocalFreeVarStaticInstantiate.java +++ b/test/langtools/tools/javac/LocalFreeVarStaticInstantiate.java @@ -1,6 +1,6 @@ /* * @test /nodynamiccopyright/ - * @bug 8322882 + * @bug 8322882 8345953 * @summary Disallow attempts to access a free variable proxy field from a static method * @compile/fail/ref=LocalFreeVarStaticInstantiate.out -XDrawDiagnostics LocalFreeVarStaticInstantiate.java */ @@ -41,4 +41,61 @@ class Local { }; } }; + + // local class in switch + static Object bar = switch (foo) { + case Runnable r -> { + Object there = ""; + class Local { + { + there.hashCode(); + } + + static { + new Local(); // can't get there from here + } + + static Runnable r = () -> { + new Local(); // can't get there from here + }; + } + yield r; + } + }; + + // local class in instance init + { + Object there = ""; + class Local { + { + there.hashCode(); + } + + static { + new Local(); // can't get there from here + } + + static Runnable r = () -> { + new Local(); // can't get there from here + }; + } + } + + // local class in static init + static { + Object there = ""; + class Local { + { + there.hashCode(); + } + + static { + new Local(); // can't get there from here + } + + static Runnable r = () -> { + new Local(); // can't get there from here + }; + } + } } diff --git a/test/langtools/tools/javac/LocalFreeVarStaticInstantiate.out b/test/langtools/tools/javac/LocalFreeVarStaticInstantiate.out index 50e913083b0..9c26cf4a527 100644 --- a/test/langtools/tools/javac/LocalFreeVarStaticInstantiate.out +++ b/test/langtools/tools/javac/LocalFreeVarStaticInstantiate.out @@ -2,4 +2,10 @@ LocalFreeVarStaticInstantiate.java:18:17: compiler.err.local.cant.be.inst.static LocalFreeVarStaticInstantiate.java:22:17: compiler.err.local.cant.be.inst.static: kindname.class, Local LocalFreeVarStaticInstantiate.java:36:17: compiler.err.local.cant.be.inst.static: kindname.class, Local LocalFreeVarStaticInstantiate.java:40:17: compiler.err.local.cant.be.inst.static: kindname.class, Local -4 errors +LocalFreeVarStaticInstantiate.java:55:21: compiler.err.local.cant.be.inst.static: kindname.class, Local +LocalFreeVarStaticInstantiate.java:59:21: compiler.err.local.cant.be.inst.static: kindname.class, Local +LocalFreeVarStaticInstantiate.java:75:17: compiler.err.local.cant.be.inst.static: kindname.class, Local +LocalFreeVarStaticInstantiate.java:79:17: compiler.err.local.cant.be.inst.static: kindname.class, Local +LocalFreeVarStaticInstantiate.java:93:17: compiler.err.local.cant.be.inst.static: kindname.class, Local +LocalFreeVarStaticInstantiate.java:97:17: compiler.err.local.cant.be.inst.static: kindname.class, Local +10 errors diff --git a/test/langtools/tools/javac/LocalFreeVarStaticSuper.java b/test/langtools/tools/javac/LocalFreeVarStaticSuper.java new file mode 100644 index 00000000000..332eb239e35 --- /dev/null +++ b/test/langtools/tools/javac/LocalFreeVarStaticSuper.java @@ -0,0 +1,161 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8345944 + * @summary JEP 492: extending local class in a different static context should not be allowed + * @compile/fail/ref=LocalFreeVarStaticSuper.out -XDrawDiagnostics LocalFreeVarStaticSuper.java + */ + +class LocalFreeVarStaticSuper { + + // local class in method + static void foo(Object there) { + class Local { + { + there.hashCode(); + } + + static { + class Sub1 extends Local { } + class Sub2 extends Local { + Sub2() { } + } + class Sub3 extends Local { + Sub3() { super(); } + } + } + + static Runnable r = () -> { + class Sub1 extends Local { } + class Sub2 extends Local { + Sub2() { } + } + class Sub3 extends Local { + Sub3() { super(); } + } + }; + } + } + + // local class in lambda + static Runnable foo = () -> { + Object there = ""; + class Local { + { + there.hashCode(); + } + + static { + class Sub1 extends Local { } + class Sub2 extends Local { + Sub2() { } + } + class Sub3 extends Local { + Sub3() { super(); } + } + } + + static Runnable r = () -> { + class Sub1 extends Local { } + class Sub2 extends Local { + Sub2() { } + } + class Sub3 extends Local { + Sub3() { super(); } + } + }; + } + }; + + // local class in switch + static Object bar = switch (foo) { + case Runnable r -> { + Object there = ""; + class Local { + { + there.hashCode(); + } + + static { + class Sub1 extends Local { } + class Sub2 extends Local { + Sub2() { } + } + class Sub3 extends Local { + Sub3() { super(); } + } + } + + static Runnable r = () -> { + class Sub1 extends Local { } + class Sub2 extends Local { + Sub2() { } + } + class Sub3 extends Local { + Sub3() { super(); } + } + }; + } + yield r; + } + }; + + // local class in instance init + { + Object there = ""; + class Local { + { + there.hashCode(); + } + + static { + class Sub1 extends Local { } + class Sub2 extends Local { + Sub2() { } + } + class Sub3 extends Local { + Sub3() { super(); } + } + } + + static Runnable r = () -> { + class Sub1 extends Local { } + class Sub2 extends Local { + Sub2() { } + } + class Sub3 extends Local { + Sub3() { super(); } + } + }; + } + } + + // local class in static init + static { + Object there = ""; + class Local { + { + there.hashCode(); + } + + static { + class Sub1 extends Local { } + class Sub2 extends Local { + Sub2() { } + } + class Sub3 extends Local { + Sub3() { super(); } + } + } + + static Runnable r = () -> { + class Sub1 extends Local { } + class Sub2 extends Local { + Sub2() { } + } + class Sub3 extends Local { + Sub3() { super(); } + } + }; + } + } +} diff --git a/test/langtools/tools/javac/LocalFreeVarStaticSuper.out b/test/langtools/tools/javac/LocalFreeVarStaticSuper.out new file mode 100644 index 00000000000..d85451337bd --- /dev/null +++ b/test/langtools/tools/javac/LocalFreeVarStaticSuper.out @@ -0,0 +1,31 @@ +LocalFreeVarStaticSuper.java:18:17: compiler.err.local.cant.be.inst.static: kindname.class, Local +LocalFreeVarStaticSuper.java:20:28: compiler.err.local.cant.be.inst.static: kindname.class, Local +LocalFreeVarStaticSuper.java:23:30: compiler.err.local.cant.be.inst.static: kindname.class, Local +LocalFreeVarStaticSuper.java:28:17: compiler.err.local.cant.be.inst.static: kindname.class, Local +LocalFreeVarStaticSuper.java:30:28: compiler.err.local.cant.be.inst.static: kindname.class, Local +LocalFreeVarStaticSuper.java:33:30: compiler.err.local.cant.be.inst.static: kindname.class, Local +LocalFreeVarStaticSuper.java:48:17: compiler.err.local.cant.be.inst.static: kindname.class, Local +LocalFreeVarStaticSuper.java:50:28: compiler.err.local.cant.be.inst.static: kindname.class, Local +LocalFreeVarStaticSuper.java:53:30: compiler.err.local.cant.be.inst.static: kindname.class, Local +LocalFreeVarStaticSuper.java:58:17: compiler.err.local.cant.be.inst.static: kindname.class, Local +LocalFreeVarStaticSuper.java:60:28: compiler.err.local.cant.be.inst.static: kindname.class, Local +LocalFreeVarStaticSuper.java:63:30: compiler.err.local.cant.be.inst.static: kindname.class, Local +LocalFreeVarStaticSuper.java:79:21: compiler.err.local.cant.be.inst.static: kindname.class, Local +LocalFreeVarStaticSuper.java:81:32: compiler.err.local.cant.be.inst.static: kindname.class, Local +LocalFreeVarStaticSuper.java:84:34: compiler.err.local.cant.be.inst.static: kindname.class, Local +LocalFreeVarStaticSuper.java:89:21: compiler.err.local.cant.be.inst.static: kindname.class, Local +LocalFreeVarStaticSuper.java:91:32: compiler.err.local.cant.be.inst.static: kindname.class, Local +LocalFreeVarStaticSuper.java:94:34: compiler.err.local.cant.be.inst.static: kindname.class, Local +LocalFreeVarStaticSuper.java:111:17: compiler.err.local.cant.be.inst.static: kindname.class, Local +LocalFreeVarStaticSuper.java:113:28: compiler.err.local.cant.be.inst.static: kindname.class, Local +LocalFreeVarStaticSuper.java:116:30: compiler.err.local.cant.be.inst.static: kindname.class, Local +LocalFreeVarStaticSuper.java:121:17: compiler.err.local.cant.be.inst.static: kindname.class, Local +LocalFreeVarStaticSuper.java:123:28: compiler.err.local.cant.be.inst.static: kindname.class, Local +LocalFreeVarStaticSuper.java:126:30: compiler.err.local.cant.be.inst.static: kindname.class, Local +LocalFreeVarStaticSuper.java:141:17: compiler.err.local.cant.be.inst.static: kindname.class, Local +LocalFreeVarStaticSuper.java:143:28: compiler.err.local.cant.be.inst.static: kindname.class, Local +LocalFreeVarStaticSuper.java:146:30: compiler.err.local.cant.be.inst.static: kindname.class, Local +LocalFreeVarStaticSuper.java:151:17: compiler.err.local.cant.be.inst.static: kindname.class, Local +LocalFreeVarStaticSuper.java:153:28: compiler.err.local.cant.be.inst.static: kindname.class, Local +LocalFreeVarStaticSuper.java:156:30: compiler.err.local.cant.be.inst.static: kindname.class, Local +30 errors diff --git a/test/langtools/tools/javac/diags/examples/ModifierNotAllowed/module-info.java b/test/langtools/tools/javac/diags/examples/ModifierNotAllowed/module-info.java index f2e5899a915..02cb11f5ac2 100644 --- a/test/langtools/tools/javac/diags/examples/ModifierNotAllowed/module-info.java +++ b/test/langtools/tools/javac/diags/examples/ModifierNotAllowed/module-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,7 +21,7 @@ * questions. */ -// key: compiler.err.feature.not.supported.in.source.plural +// key: compiler.err.preview.feature.disabled.plural // key: compiler.misc.feature.java.base.transitive module m { diff --git a/test/langtools/tools/javac/modules/AnnotationsOnModules.java b/test/langtools/tools/javac/modules/AnnotationsOnModules.java index 65019854360..291633b4fb2 100644 --- a/test/langtools/tools/javac/modules/AnnotationsOnModules.java +++ b/test/langtools/tools/javac/modules/AnnotationsOnModules.java @@ -804,7 +804,7 @@ public class C {} .writeAll() .getOutputLines(OutputKind.DIRECT); List<String> expectedErrors = List.of( - "- compiler.err.cant.access: m.module-info, (compiler.misc.bad.class.file.header: module-info.class, (compiler.misc.bad.requires.flag: ACC_TRANSITIVE (0x0020))", + "- compiler.err.cant.access: m.module-info, (compiler.misc.bad.class.file.header: module-info.class, (compiler.misc.bad.requires.flag: ACC_TRANSITIVE (0x0020)))", "1 error" ); diff --git a/test/langtools/tools/javac/modules/JavaBaseTest.java b/test/langtools/tools/javac/modules/JavaBaseTest.java index 935ddfa1d43..a888c430f53 100644 --- a/test/langtools/tools/javac/modules/JavaBaseTest.java +++ b/test/langtools/tools/javac/modules/JavaBaseTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -166,7 +166,7 @@ void testSource(Path base, List<String> mods, String target) throws Exception { for (String mod : mods) { String key = mod.equals("static") ? "compiler.err.mod.not.allowed.here: " + mod - : "compiler.err.feature.not.supported.in.source.plural: (compiler.misc.feature.java.base.transitive)"; + : "compiler.err.preview.feature.disabled.plural: (compiler.misc.feature.java.base.transitive)"; String message = "module-info.java:1:12: " + key; if (log.contains(message)) { foundErrorMessage = true;