diff --git a/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp b/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp index c7cf678b49ecf..3b48b4020ccb3 100644 --- a/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp @@ -2170,7 +2170,6 @@ do { \ (result == R8_ARG6 || result == noreg), "registers must match ppc64.ad"); \ } while(0) -// Return true: we succeeded in generating this code void MacroAssembler::lookup_secondary_supers_table(Register r_sub_klass, Register r_super_klass, Register temp1, @@ -2292,9 +2291,8 @@ void MacroAssembler::lookup_secondary_supers_table_slow_path(Register r_super_kl // The bitmap is full to bursting. // Implicit invariant: BITMAP_FULL implies (length > 0) - assert(Klass::SECONDARY_SUPERS_BITMAP_FULL == ~uintx(0), ""); - cmpdi(CCR0, r_bitmap, -1); - beq(CCR0, L_huge); + cmpwi(CCR0, r_array_length, (int32_t)Klass::SECONDARY_SUPERS_TABLE_SIZE - 2); + bgt(CCR0, L_huge); // NB! Our caller has checked bits 0 and 1 in the bitmap. The // current slot (at secondary_supers[r_array_index]) has not yet diff --git a/src/hotspot/cpu/s390/macroAssembler_s390.cpp b/src/hotspot/cpu/s390/macroAssembler_s390.cpp index a233934405f78..b31d08f9fde10 100644 --- a/src/hotspot/cpu/s390/macroAssembler_s390.cpp +++ b/src/hotspot/cpu/s390/macroAssembler_s390.cpp @@ -3320,8 +3320,8 @@ void MacroAssembler::lookup_secondary_supers_table_slow_path(Register r_super_kl NearLabel L_huge; // The bitmap is full to bursting. - z_cghi(r_bitmap, Klass::SECONDARY_SUPERS_BITMAP_FULL); - z_bre(L_huge); + z_chi(r_array_length, Klass::SECONDARY_SUPERS_BITMAP_FULL - 2); + z_brh(L_huge); // NB! Our caller has checked bits 0 and 1 in the bitmap. The // current slot (at secondary_supers[r_array_index]) has not yet diff --git a/src/hotspot/share/gc/shenandoah/shenandoahAsserts.cpp b/src/hotspot/share/gc/shenandoah/shenandoahAsserts.cpp index 8235b59b80e56..1539c7c2c5daa 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahAsserts.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahAsserts.cpp @@ -37,7 +37,7 @@ void print_raw_memory(ShenandoahMessageBuffer &msg, void* loc) { // should be in heap, in known committed region, within that region. ShenandoahHeap* heap = ShenandoahHeap::heap(); - if (!heap->is_in(loc)) return; + if (!heap->is_in_reserved(loc)) return; ShenandoahHeapRegion* r = heap->heap_region_containing(loc); if (r != nullptr && r->is_committed()) { @@ -77,7 +77,7 @@ void ShenandoahAsserts::print_obj(ShenandoahMessageBuffer& msg, oop obj) { void ShenandoahAsserts::print_non_obj(ShenandoahMessageBuffer& msg, void* loc) { ShenandoahHeap* heap = ShenandoahHeap::heap(); - if (heap->is_in(loc)) { + if (heap->is_in_reserved(loc)) { msg.append(" inside Java heap\n"); ShenandoahHeapRegion *r = heap->heap_region_containing(loc); stringStream ss; @@ -96,7 +96,7 @@ void ShenandoahAsserts::print_non_obj(ShenandoahMessageBuffer& msg, void* loc) { void ShenandoahAsserts::print_obj_safe(ShenandoahMessageBuffer& msg, void* loc) { ShenandoahHeap* heap = ShenandoahHeap::heap(); msg.append(" " PTR_FORMAT " - safe print, no details\n", p2i(loc)); - if (heap->is_in(loc)) { + if (heap->is_in_reserved(loc)) { ShenandoahHeapRegion* r = heap->heap_region_containing(loc); if (r != nullptr) { stringStream ss; @@ -113,7 +113,7 @@ void ShenandoahAsserts::print_failure(SafeLevel level, oop obj, void* interior_l ShenandoahHeap* heap = ShenandoahHeap::heap(); ResourceMark rm; - bool loc_in_heap = (loc != nullptr && heap->is_in(loc)); + bool loc_in_heap = (loc != nullptr && heap->is_in_reserved(loc)); ShenandoahMessageBuffer msg("%s; %s\n\n", phase, label); @@ -166,22 +166,22 @@ void ShenandoahAsserts::print_failure(SafeLevel level, oop obj, void* interior_l report_vm_error(file, line, msg.buffer()); } -void ShenandoahAsserts::assert_in_heap(void* interior_loc, oop obj, const char *file, int line) { +void ShenandoahAsserts::assert_in_heap_bounds(void* interior_loc, oop obj, const char *file, int line) { ShenandoahHeap* heap = ShenandoahHeap::heap(); - if (!heap->is_in(obj)) { - print_failure(_safe_unknown, obj, interior_loc, nullptr, "Shenandoah assert_in_heap failed", - "oop must point to a heap address", + if (!heap->is_in_reserved(obj)) { + print_failure(_safe_unknown, obj, interior_loc, nullptr, "Shenandoah assert_in_heap_bounds failed", + "oop must be in heap bounds", file, line); } } -void ShenandoahAsserts::assert_in_heap_or_null(void* interior_loc, oop obj, const char *file, int line) { +void ShenandoahAsserts::assert_in_heap_bounds_or_null(void* interior_loc, oop obj, const char *file, int line) { ShenandoahHeap* heap = ShenandoahHeap::heap(); - if (obj != nullptr && !heap->is_in(obj)) { - print_failure(_safe_unknown, obj, interior_loc, nullptr, "Shenandoah assert_in_heap_or_null failed", - "oop must point to a heap address", + if (obj != nullptr && !heap->is_in_reserved(obj)) { + print_failure(_safe_unknown, obj, interior_loc, nullptr, "Shenandoah assert_in_heap_bounds_or_null failed", + "oop must be in heap bounds", file, line); } } @@ -191,9 +191,9 @@ void ShenandoahAsserts::assert_correct(void* interior_loc, oop obj, const char* // Step 1. Check that obj is correct. // After this step, it is safe to call heap_region_containing(). - if (!heap->is_in(obj)) { + if (!heap->is_in_reserved(obj)) { print_failure(_safe_unknown, obj, interior_loc, nullptr, "Shenandoah assert_correct failed", - "oop must point to a heap address", + "oop must be in heap bounds", file, line); } @@ -210,6 +210,12 @@ void ShenandoahAsserts::assert_correct(void* interior_loc, oop obj, const char* file,line); } + if (!heap->is_in(obj)) { + print_failure(_safe_unknown, obj, interior_loc, nullptr, "Shenandoah assert_correct failed", + "Object should be in active region area", + file, line); + } + oop fwd = ShenandoahForwarding::get_forwardee_raw_unchecked(obj); if (obj != fwd) { @@ -223,9 +229,9 @@ void ShenandoahAsserts::assert_correct(void* interior_loc, oop obj, const char* } // Step 2. Check that forwardee is correct - if (!heap->is_in(fwd)) { + if (!heap->is_in_reserved(fwd)) { print_failure(_safe_oop, obj, interior_loc, nullptr, "Shenandoah assert_correct failed", - "Forwardee must point to a heap address", + "Forwardee must be in heap bounds", file, line); } @@ -236,9 +242,15 @@ void ShenandoahAsserts::assert_correct(void* interior_loc, oop obj, const char* } // Step 3. Check that forwardee points to correct region + if (!heap->is_in(fwd)) { + print_failure(_safe_oop, obj, interior_loc, nullptr, "Shenandoah assert_correct failed", + "Forwardee should be in active region area", + file, line); + } + if (heap->heap_region_index_containing(fwd) == heap->heap_region_index_containing(obj)) { print_failure(_safe_all, obj, interior_loc, nullptr, "Shenandoah assert_correct failed", - "Non-trivial forwardee should in another region", + "Non-trivial forwardee should be in another region", file, line); } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahAsserts.hpp b/src/hotspot/share/gc/shenandoah/shenandoahAsserts.hpp index c730eafb89d01..154edebcf3edc 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahAsserts.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahAsserts.hpp @@ -53,8 +53,8 @@ class ShenandoahAsserts { static void print_rp_failure(const char *label, BoolObjectClosure* actual, const char *file, int line); - static void assert_in_heap(void* interior_loc, oop obj, const char* file, int line); - static void assert_in_heap_or_null(void* interior_loc, oop obj, const char* file, int line); + static void assert_in_heap_bounds(void* interior_loc, oop obj, const char* file, int line); + static void assert_in_heap_bounds_or_null(void* interior_loc, oop obj, const char* file, int line); static void assert_in_correct_region(void* interior_loc, oop obj, const char* file, int line); static void assert_correct(void* interior_loc, oop obj, const char* file, int line); @@ -74,10 +74,10 @@ class ShenandoahAsserts { static void assert_heaplocked_or_safepoint(const char* file, int line); #ifdef ASSERT -#define shenandoah_assert_in_heap(interior_loc, obj) \ - ShenandoahAsserts::assert_in_heap(interior_loc, obj, __FILE__, __LINE__) -#define shenandoah_assert_in_heap_or_null(interior_loc, obj) \ - ShenandoahAsserts::assert_in_heap_or_null(interior_loc, obj, __FILE__, __LINE__) +#define shenandoah_assert_in_heap_bounds(interior_loc, obj) \ + ShenandoahAsserts::assert_in_heap_bounds(interior_loc, obj, __FILE__, __LINE__) +#define shenandoah_assert_in_heap_bounds_or_null(interior_loc, obj) \ + ShenandoahAsserts::assert_in_heap_bounds_or_null(interior_loc, obj, __FILE__, __LINE__) #define shenandoah_assert_in_correct_region(interior_loc, obj) \ ShenandoahAsserts::assert_in_correct_region(interior_loc, obj, __FILE__, __LINE__) @@ -164,8 +164,8 @@ class ShenandoahAsserts { #define shenandoah_assert_heaplocked_or_safepoint() \ ShenandoahAsserts::assert_heaplocked_or_safepoint(__FILE__, __LINE__) #else -#define shenandoah_assert_in_heap(interior_loc, obj) -#define shenandoah_assert_in_heap_or_null(interior_loc, obj) +#define shenandoah_assert_in_heap_bounds(interior_loc, obj) +#define shenandoah_assert_in_heap_bounds_or_null(interior_loc, obj) #define shenandoah_assert_in_correct_region(interior_loc, obj) #define shenandoah_assert_correct_if(interior_loc, obj, condition) diff --git a/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.inline.hpp index 6eb026561e46e..cceebae0b1c63 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.inline.hpp @@ -41,12 +41,12 @@ bool ShenandoahCollectionSet::is_in(ShenandoahHeapRegion* r) const { } bool ShenandoahCollectionSet::is_in(oop p) const { - shenandoah_assert_in_heap_or_null(nullptr, p); + shenandoah_assert_in_heap_bounds_or_null(nullptr, p); return is_in_loc(cast_from_oop(p)); } bool ShenandoahCollectionSet::is_in_loc(void* p) const { - assert(p == nullptr || _heap->is_in(p), "Must be in the heap"); + assert(p == nullptr || _heap->is_in_reserved(p), "Must be in the heap"); uintx index = ((uintx) p) >> _region_size_bytes_shift; // no need to subtract the bottom of the heap from p, // _biased_cset_map is biased diff --git a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp index 0301ef422a629..0e18b59103746 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp @@ -718,7 +718,7 @@ void ShenandoahEvacUpdateCleanupOopStorageRootsClosure::do_oop(oop* p) { const oop obj = RawAccess<>::oop_load(p); if (!CompressedOops::is_null(obj)) { if (!_mark_context->is_marked(obj)) { - shenandoah_assert_correct(p, obj); + // Note: The obj is dead here. Do not touch it, just clear. ShenandoahHeap::atomic_clear_oop(p, obj); } else if (_evac_in_progress && _heap->in_collection_set(obj)) { oop resolved = ShenandoahBarrierSet::resolve_forwarded_not_null(obj); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahForwarding.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahForwarding.inline.hpp index cf69eb67e4754..01294f9c8908b 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahForwarding.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahForwarding.inline.hpp @@ -32,7 +32,7 @@ #include "runtime/javaThread.hpp" inline oop ShenandoahForwarding::get_forwardee_raw(oop obj) { - shenandoah_assert_in_heap(nullptr, obj); + shenandoah_assert_in_heap_bounds(nullptr, obj); return get_forwardee_raw_unchecked(obj); } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp index 6f5fce53f85b5..a587cc417e319 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp @@ -730,9 +730,18 @@ size_t ShenandoahHeap::initial_capacity() const { } bool ShenandoahHeap::is_in(const void* p) const { - HeapWord* heap_base = (HeapWord*) base(); - HeapWord* last_region_end = heap_base + ShenandoahHeapRegion::region_size_words() * num_regions(); - return p >= heap_base && p < last_region_end; + if (is_in_reserved(p)) { + if (is_full_gc_move_in_progress()) { + // Full GC move is running, we do not have a consistent region + // information yet. But we know the pointer is in heap. + return true; + } + // Now check if we point to a live section in active region. + ShenandoahHeapRegion* r = heap_region_containing(p); + return (r->is_active() && p < r->top()); + } else { + return false; + } } void ShenandoahHeap::maybe_uncommit(double shrink_before, size_t shrink_until) { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp index 81b1c3df6f411..1ee1f9dfc88be 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp @@ -493,6 +493,8 @@ class ShenandoahHeap : public CollectedHeap, public ShenandoahSpaceInfo { public: bool is_maximal_no_gc() const override shenandoah_not_implemented_return(false); + // Check the pointer is in active part of Java heap. + // Use is_in_reserved to check if object is within heap bounds. bool is_in(const void* p) const override; bool requires_barriers(stackChunkOop obj) const override; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahMarkBitMap.cpp b/src/hotspot/share/gc/shenandoah/shenandoahMarkBitMap.cpp index 30389b4e95cdd..fa2e15a98c74b 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahMarkBitMap.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahMarkBitMap.cpp @@ -122,7 +122,7 @@ void ShenandoahMarkBitMap::clear_range_large(MemRegion mr) { #ifdef ASSERT void ShenandoahMarkBitMap::check_mark(HeapWord* addr) const { - assert(ShenandoahHeap::heap()->is_in(addr), + assert(ShenandoahHeap::heap()->is_in_reserved(addr), "Trying to access bitmap " PTR_FORMAT " for address " PTR_FORMAT " not in the heap.", p2i(this), p2i(addr)); } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.hpp b/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.hpp index d58117c02e2d6..62baf3e61eaef 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.hpp @@ -63,8 +63,10 @@ class ShenandoahMarkingContext : public CHeapObj { inline bool mark_weak(oop obj); // Simple versions of marking accessors, to be used outside of marking (e.g. no possible concurrent updates) - inline bool is_marked(oop) const; + inline bool is_marked(oop obj) const; + inline bool is_marked(HeapWord* raw_obj) const; inline bool is_marked_strong(oop obj) const; + inline bool is_marked_strong(HeapWord* raw_obj) const; inline bool is_marked_weak(oop obj) const; inline HeapWord* get_next_marked_addr(HeapWord* addr, HeapWord* limit) const; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.inline.hpp index 34b8288f47673..1ba3caf26b72b 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.inline.hpp @@ -38,11 +38,19 @@ inline bool ShenandoahMarkingContext::mark_weak(oop obj) { } inline bool ShenandoahMarkingContext::is_marked(oop obj) const { - return allocated_after_mark_start(obj) || _mark_bit_map.is_marked(cast_from_oop(obj)); + return is_marked(cast_from_oop(obj)); +} + +inline bool ShenandoahMarkingContext::is_marked(HeapWord* raw_obj) const { + return allocated_after_mark_start(raw_obj) || _mark_bit_map.is_marked(raw_obj); } inline bool ShenandoahMarkingContext::is_marked_strong(oop obj) const { - return allocated_after_mark_start(obj) || _mark_bit_map.is_marked_strong(cast_from_oop(obj)); + return is_marked_strong(cast_from_oop(obj)); +} + +inline bool ShenandoahMarkingContext::is_marked_strong(HeapWord* raw_obj) const { + return allocated_after_mark_start(raw_obj) || _mark_bit_map.is_marked_strong(raw_obj); } inline bool ShenandoahMarkingContext::is_marked_weak(oop obj) const { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahReferenceProcessor.cpp b/src/hotspot/share/gc/shenandoah/shenandoahReferenceProcessor.cpp index f395119d46a35..42c8d0ad27112 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahReferenceProcessor.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahReferenceProcessor.cpp @@ -83,10 +83,21 @@ static volatile T* reference_referent_addr(oop reference) { return (volatile T*)java_lang_ref_Reference::referent_addr_raw(reference); } +inline oop reference_coop_decode_raw(narrowOop v) { + return CompressedOops::is_null(v) ? nullptr : CompressedOops::decode_raw(v); +} + +inline oop reference_coop_decode_raw(oop v) { + return v; +} + +// Raw referent, it can be dead. You cannot treat it as oop without additional safety +// checks, this is why it is HeapWord*. The decoding uses a special-case inlined +// CompressedOops::decode method that bypasses normal oop-ness checks. template -static oop reference_referent(oop reference) { - T heap_oop = Atomic::load(reference_referent_addr(reference)); - return CompressedOops::decode(heap_oop); +static HeapWord* reference_referent_raw(oop reference) { + T raw_oop = Atomic::load(reference_referent_addr(reference)); + return cast_from_oop(reference_coop_decode_raw(raw_oop)); } static void reference_clear_referent(oop reference) { @@ -278,8 +289,8 @@ bool ShenandoahReferenceProcessor::should_discover(oop reference, ReferenceType template bool ShenandoahReferenceProcessor::should_drop(oop reference, ReferenceType type) const { - const oop referent = reference_referent(reference); - if (referent == nullptr) { + HeapWord* raw_referent = reference_referent_raw(reference); + if (raw_referent == nullptr) { // Reference has been cleared, by a call to Reference.enqueue() // or Reference.clear() from the application, which means we // should drop the reference. @@ -289,9 +300,9 @@ bool ShenandoahReferenceProcessor::should_drop(oop reference, ReferenceType type // Check if the referent is still alive, in which case we should // drop the reference. if (type == REF_PHANTOM) { - return ShenandoahHeap::heap()->complete_marking_context()->is_marked(referent); + return ShenandoahHeap::heap()->complete_marking_context()->is_marked(raw_referent); } else { - return ShenandoahHeap::heap()->complete_marking_context()->is_marked_strong(referent); + return ShenandoahHeap::heap()->complete_marking_context()->is_marked_strong(raw_referent); } } @@ -303,7 +314,7 @@ void ShenandoahReferenceProcessor::make_inactive(oop reference, ReferenceType ty // next field. An application can't call FinalReference.enqueue(), so there is // no race to worry about when setting the next field. assert(reference_next(reference) == nullptr, "Already inactive"); - assert(ShenandoahHeap::heap()->marking_context()->is_marked(reference_referent(reference)), "only make inactive final refs with alive referents"); + assert(ShenandoahHeap::heap()->marking_context()->is_marked(reference_referent_raw(reference)), "only make inactive final refs with alive referents"); reference_set_next(reference, reference); } else { // Clear referent @@ -376,8 +387,8 @@ oop ShenandoahReferenceProcessor::drop(oop reference, ReferenceType type) { log_trace(gc, ref)("Dropped Reference: " PTR_FORMAT " (%s)", p2i(reference), reference_type_name(type)); #ifdef ASSERT - oop referent = reference_referent(reference); - assert(referent == nullptr || ShenandoahHeap::heap()->marking_context()->is_marked(referent), + HeapWord* raw_referent = reference_referent_raw(reference); + assert(raw_referent == nullptr || ShenandoahHeap::heap()->marking_context()->is_marked(raw_referent), "only drop references with alive referents"); #endif diff --git a/src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp b/src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp index 23da3d7f63709..4834ecba54390 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp @@ -51,13 +51,6 @@ static bool is_instance_ref_klass(Klass* k) { return k->is_instance_klass() && InstanceKlass::cast(k)->reference_type() != REF_NONE; } -class ShenandoahIgnoreReferenceDiscoverer : public ReferenceDiscoverer { -public: - virtual bool discover_reference(oop obj, ReferenceType type) { - return true; - } -}; - class ShenandoahVerifyOopClosure : public BasicOopIterateClosure { private: const char* _phase; @@ -68,6 +61,7 @@ class ShenandoahVerifyOopClosure : public BasicOopIterateClosure { ShenandoahLivenessData* _ld; void* _interior_loc; oop _loc; + ReferenceIterationMode _ref_mode; public: ShenandoahVerifyOopClosure(ShenandoahVerifierStack* stack, MarkBitMap* map, ShenandoahLivenessData* ld, @@ -82,10 +76,20 @@ class ShenandoahVerifyOopClosure : public BasicOopIterateClosure { _loc(nullptr) { if (options._verify_marked == ShenandoahVerifier::_verify_marked_complete_except_references || options._verify_marked == ShenandoahVerifier::_verify_marked_disable) { - set_ref_discoverer_internal(new ShenandoahIgnoreReferenceDiscoverer()); + // Unknown status for Reference.referent field. Do not touch it, it might be dead. + // Normally, barriers would prevent us from seeing the dead referents, but verifier + // runs with barriers disabled. + _ref_mode = DO_FIELDS_EXCEPT_REFERENT; + } else { + // Otherwise do all fields. + _ref_mode = DO_FIELDS; } } + ReferenceIterationMode reference_iteration_mode() override { + return _ref_mode; + } + private: void check(ShenandoahAsserts::SafeLevel level, oop obj, bool test, const char* label) { if (!test) { @@ -119,8 +123,8 @@ class ShenandoahVerifyOopClosure : public BasicOopIterateClosure { // that failure report would not try to touch something that was not yet verified to be // safe to process. - check(ShenandoahAsserts::_safe_unknown, obj, _heap->is_in(obj), - "oop must be in heap"); + check(ShenandoahAsserts::_safe_unknown, obj, _heap->is_in_reserved(obj), + "oop must be in heap bounds"); check(ShenandoahAsserts::_safe_unknown, obj, is_object_aligned(obj), "oop must be aligned"); @@ -177,8 +181,8 @@ class ShenandoahVerifyOopClosure : public BasicOopIterateClosure { ShenandoahHeapRegion* fwd_reg = nullptr; if (obj != fwd) { - check(ShenandoahAsserts::_safe_oop, obj, _heap->is_in(fwd), - "Forwardee must be in heap"); + check(ShenandoahAsserts::_safe_oop, obj, _heap->is_in_reserved(fwd), + "Forwardee must be in heap bounds"); check(ShenandoahAsserts::_safe_oop, obj, !CompressedOops::is_null(fwd), "Forwardee is set"); check(ShenandoahAsserts::_safe_oop, obj, is_object_aligned(fwd), @@ -195,6 +199,9 @@ class ShenandoahVerifyOopClosure : public BasicOopIterateClosure { fwd_reg = _heap->heap_region_containing(fwd); + check(ShenandoahAsserts::_safe_oop, obj, fwd_reg->is_active(), + "Forwardee should be in active region"); + // Verify that forwardee is not in the dead space: check(ShenandoahAsserts::_safe_oop, obj, !fwd_reg->is_humongous(), "Should have no humongous forwardees"); @@ -324,8 +331,8 @@ class ShenandoahVerifyOopClosure : public BasicOopIterateClosure { _loc = nullptr; } - virtual void do_oop(oop* p) { do_oop_work(p); } - virtual void do_oop(narrowOop* p) { do_oop_work(p); } + virtual void do_oop(oop* p) override { do_oop_work(p); } + virtual void do_oop(narrowOop* p) override { do_oop_work(p); } }; class ShenandoahCalculateRegionStatsClosure : public ShenandoahHeapRegionClosure { diff --git a/src/hotspot/share/services/classLoadingService.cpp b/src/hotspot/share/services/classLoadingService.cpp index 2df8d12278d9a..09da45dc079d2 100644 --- a/src/hotspot/share/services/classLoadingService.cpp +++ b/src/hotspot/share/services/classLoadingService.cpp @@ -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 @@ -128,6 +128,22 @@ bool ClassLoadingService::set_verbose(bool verbose) { return verbose; } +bool ClassLoadingService::get_verbose() { + for (LogTagSet* ts = LogTagSet::first(); ts != nullptr; ts = ts->next()) { + // set_verbose looks for a non-exact match for class+load, + // so look for all tag sets that match class+load* + if (ts->contains(LogTag::_class) && + ts->contains(LogTag::_load)) { + LogLevelType l = ts->level_for(LogConfiguration::StdoutLog); + if (l != LogLevel::Info && l != LogLevel::Debug && l != LogLevel::Trace) { + return false; + } + } + } + + return true; +} + // Caller to this function must own Management_lock void ClassLoadingService::reset_trace_class_unloading() { assert(Management_lock->owned_by_self(), "Must own the Management_lock"); diff --git a/src/hotspot/share/services/classLoadingService.hpp b/src/hotspot/share/services/classLoadingService.hpp index f9db3da50918b..3aeb3f556a5e2 100644 --- a/src/hotspot/share/services/classLoadingService.hpp +++ b/src/hotspot/share/services/classLoadingService.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2019, 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 @@ -53,6 +53,7 @@ class ClassLoadingService : public AllStatic { public: static void init() NOT_MANAGEMENT_RETURN; static bool set_verbose(bool verbose) NOT_MANAGEMENT_RETURN_(false); + static bool get_verbose() NOT_MANAGEMENT_RETURN_(false); static void reset_trace_class_unloading() NOT_MANAGEMENT_RETURN; static jlong loaded_class_count() NOT_MANAGEMENT_RETURN_(0L); static jlong unloaded_class_count() NOT_MANAGEMENT_RETURN_(0L); @@ -63,7 +64,6 @@ class ClassLoadingService : public AllStatic { static jlong loaded_shared_class_bytes() NOT_MANAGEMENT_RETURN_(0L); static jlong unloaded_shared_class_bytes() NOT_MANAGEMENT_RETURN_(0L); static jlong class_method_data_size() NOT_MANAGEMENT_RETURN_(0L); - static bool get_verbose() { return log_is_enabled(Info, class, load); } static void notify_class_loaded(InstanceKlass* k, bool shared_class) NOT_MANAGEMENT_RETURN; diff --git a/src/hotspot/share/services/memoryService.cpp b/src/hotspot/share/services/memoryService.cpp index 21b773e204e63..de30bee12bdd3 100644 --- a/src/hotspot/share/services/memoryService.cpp +++ b/src/hotspot/share/services/memoryService.cpp @@ -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 @@ -202,6 +202,21 @@ bool MemoryService::set_verbose(bool verbose) { return verbose; } +bool MemoryService::get_verbose() { + for (LogTagSet* ts = LogTagSet::first(); ts != nullptr; ts = ts->next()) { + // set_verbose only sets gc and not gc*, so check for an exact match + const bool is_gc_exact_match = ts->contains(LogTag::_gc) && ts->ntags() == 1; + if (is_gc_exact_match) { + LogLevelType l = ts->level_for(LogConfiguration::StdoutLog); + if (l == LogLevel::Info || l == LogLevel::Debug || l == LogLevel::Trace) { + return true; + } + } + } + + return false; +} + Handle MemoryService::create_MemoryUsage_obj(MemoryUsage usage, TRAPS) { InstanceKlass* ik = Management::java_lang_management_MemoryUsage_klass(CHECK_NH); diff --git a/src/hotspot/share/services/memoryService.hpp b/src/hotspot/share/services/memoryService.hpp index 2d28f25c69519..d10c3d2e9d96e 100644 --- a/src/hotspot/share/services/memoryService.hpp +++ b/src/hotspot/share/services/memoryService.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2019, 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 @@ -106,8 +106,8 @@ class MemoryService : public AllStatic { GCCause::Cause cause, bool allMemoryPoolsAffected, const char* notificationMessage = nullptr); - static bool get_verbose() { return log_is_enabled(Info, gc); } static bool set_verbose(bool verbose); + static bool get_verbose(); // Create an instance of java/lang/management/MemoryUsage static Handle create_MemoryUsage_obj(MemoryUsage usage, TRAPS); diff --git a/src/java.base/share/classes/java/lang/classfile/ClassBuilder.java b/src/java.base/share/classes/java/lang/classfile/ClassBuilder.java index 7ad6e94df3fce..98371c9e15a61 100644 --- a/src/java.base/share/classes/java/lang/classfile/ClassBuilder.java +++ b/src/java.base/share/classes/java/lang/classfile/ClassBuilder.java @@ -276,10 +276,7 @@ default ClassBuilder withMethodBody(String name, MethodTypeDesc descriptor, int methodFlags, Consumer handler) { - return withMethodBody(constantPool().utf8Entry(name), - constantPool().utf8Entry(descriptor), - methodFlags, - handler); + return withMethod(name, descriptor, methodFlags, mb -> mb.withCode(handler)); } /** diff --git a/src/java.base/share/classes/java/net/DatagramSocket.java b/src/java.base/share/classes/java/net/DatagramSocket.java index 9e94d1d8b6209..655b00bb8b6e1 100644 --- a/src/java.base/share/classes/java/net/DatagramSocket.java +++ b/src/java.base/share/classes/java/net/DatagramSocket.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 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 @@ -395,7 +395,7 @@ public DatagramSocket(int port, InetAddress laddr) throws SocketException { * * @param addr The address and port to bind to. * @throws SocketException if any error happens during the bind, or if the - * socket is already bound. + * socket is already bound or is closed. * @throws SecurityException if a security manager exists and its * {@code checkListen} method doesn't allow the operation. * @throws IllegalArgumentException if addr is a SocketAddress subclass @@ -422,6 +422,11 @@ public void bind(SocketAddress addr) throws SocketException { * call to send or receive may throw a PortUnreachableException. Note, * there is no guarantee that the exception will be thrown. * + *

If this socket is already connected, then this method will attempt to + * connect to the given address. If this connect fails then the state of + * this socket is unknown - it may or may not be connected to the address + * that it was previously connected to. + * *

If a security manager has been installed then it is invoked to check * access to the remote address. Specifically, if the given {@code address} * is a {@link InetAddress#isMulticastAddress multicast address}, @@ -461,7 +466,7 @@ public void bind(SocketAddress addr) throws SocketException { * not permit access to the given remote address * * @throws UncheckedIOException - * may be thrown if connect fails, for example, if the + * if the port is 0 or connect fails, for example, if the * destination address is non-routable * * @see #disconnect @@ -484,6 +489,11 @@ public void connect(InetAddress address, int port) { * have not been {@linkplain #receive(DatagramPacket) received} before invoking * this method, may be discarded. * + *

If this socket is already connected, then this method will attempt to + * connect to the given address. If this connect fails then the state of + * this socket is unknown - it may or may not be connected to the address + * that it was previously connected to. + * * @param addr The remote address. * * @throws SocketException @@ -643,7 +653,7 @@ public SocketAddress getLocalSocketAddress() { * * @param p the {@code DatagramPacket} to be sent. * - * @throws IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs, or the socket is closed. * @throws SecurityException if a security manager exists and its * {@code checkMulticast} or {@code checkConnect} * method doesn't allow the send. @@ -702,7 +712,7 @@ public void send(DatagramPacket p) throws IOException { * * @param p the {@code DatagramPacket} into which to place * the incoming data. - * @throws IOException if an I/O error occurs. + * @throws IOException if an I/O error occurs, or the socket is closed. * @throws SocketTimeoutException if setSoTimeout was previously called * and the timeout has expired. * @throws PortUnreachableException may be thrown if the socket is connected @@ -770,7 +780,8 @@ public int getLocalPort() { * operation to have effect. * * @param timeout the specified timeout in milliseconds. - * @throws SocketException if there is an error in the underlying protocol, such as an UDP error. + * @throws SocketException if there is an error in the underlying protocol, + * such as an UDP error, or the socket is closed. * @throws IllegalArgumentException if {@code timeout} is negative * @since 1.1 * @see #getSoTimeout() @@ -784,7 +795,8 @@ public void setSoTimeout(int timeout) throws SocketException { * option is disabled (i.e., timeout of infinity). * * @return the setting for SO_TIMEOUT - * @throws SocketException if there is an error in the underlying protocol, such as an UDP error. + * @throws SocketException if there is an error in the underlying protocol, + * such as an UDP error, or the socket is closed. * @since 1.1 * @see #setSoTimeout(int) */ @@ -820,8 +832,8 @@ public int getSoTimeout() throws SocketException { * @param size the size to which to set the send buffer * size, in bytes. This value must be greater than 0. * - * @throws SocketException if there is an error - * in the underlying protocol, such as an UDP error. + * @throws SocketException if there is an error in the underlying protocol, + * such as an UDP error, or the socket is closed. * @throws IllegalArgumentException if the value is 0 or is * negative. * @see #getSendBufferSize() @@ -841,8 +853,8 @@ public void setSendBufferSize(int size) throws SocketException { * getOption(StandardSocketOptions.SO_SNDBUF)}. * * @return the value of the SO_SNDBUF option for this {@code DatagramSocket} - * @throws SocketException if there is an error in - * the underlying protocol, such as an UDP error. + * @throws SocketException if there is an error in the underlying protocol, + * such as an UDP error, or the socket is closed. * @see #setSendBufferSize * @see StandardSocketOptions#SO_SNDBUF * @since 1.2 @@ -878,8 +890,8 @@ public int getSendBufferSize() throws SocketException { * @param size the size to which to set the receive buffer * size, in bytes. This value must be greater than 0. * - * @throws SocketException if there is an error in - * the underlying protocol, such as an UDP error. + * @throws SocketException if there is an error in the underlying protocol, + * such as an UDP error, or the socket is closed. * @throws IllegalArgumentException if the value is 0 or is * negative. * @see #getReceiveBufferSize() @@ -899,7 +911,8 @@ public void setReceiveBufferSize(int size) throws SocketException { * getOption(StandardSocketOptions.SO_RCVBUF)}. * * @return the value of the SO_RCVBUF option for this {@code DatagramSocket} - * @throws SocketException if there is an error in the underlying protocol, such as an UDP error. + * @throws SocketException if there is an error in the underlying protocol, + * such as an UDP error, or the socket is closed. * @see #setReceiveBufferSize(int) * @see StandardSocketOptions#SO_RCVBUF * @since 1.2 @@ -959,8 +972,8 @@ public void setReuseAddress(boolean on) throws SocketException { * getOption(StandardSocketOptions.SO_REUSEADDR)}. * * @return a {@code boolean} indicating whether or not SO_REUSEADDR is enabled. - * @throws SocketException if there is an error - * in the underlying protocol, such as an UDP error. + * @throws SocketException if there is an error in the underlying protocol, + * such as an UDP error, or the socket is closed. * @since 1.4 * @see #setReuseAddress(boolean) * @see StandardSocketOptions#SO_REUSEADDR @@ -983,9 +996,8 @@ public boolean getReuseAddress() throws SocketException { * @param on * whether or not to have broadcast turned on. * - * @throws SocketException - * if there is an error in the underlying protocol, such as an UDP - * error. + * @throws SocketException if there is an error in the underlying protocol, + * such as an UDP error, or the socket is closed. * * @since 1.4 * @see #getBroadcast() @@ -1003,8 +1015,8 @@ public void setBroadcast(boolean on) throws SocketException { * getOption(StandardSocketOptions.SO_BROADCAST)}. * * @return a {@code boolean} indicating whether or not SO_BROADCAST is enabled. - * @throws SocketException if there is an error - * in the underlying protocol, such as an UDP error. + * @throws SocketException if there is an error in the underlying protocol, + * such as an UDP error, or the socket is closed. * @since 1.4 * @see #setBroadcast(boolean) * @see StandardSocketOptions#SO_BROADCAST @@ -1049,8 +1061,8 @@ public boolean getBroadcast() throws SocketException { * setOption(StandardSocketOptions.IP_TOS, tc)}. * * @param tc an {@code int} value for the bitset. - * @throws SocketException if there is an error setting the - * traffic class or type-of-service + * @throws SocketException if there is an error setting the traffic class or type-of-service, + * or the socket is closed. * @since 1.4 * @see #getTrafficClass * @see StandardSocketOptions#IP_TOS @@ -1074,8 +1086,8 @@ public void setTrafficClass(int tc) throws SocketException { * getOption(StandardSocketOptions.IP_TOS)}. * * @return the traffic class or type-of-service already set - * @throws SocketException if there is an error obtaining the - * traffic class or type-of-service value. + * @throws SocketException if there is an error obtaining the traffic class + * or type-of-service value, or the socket is closed. * @since 1.4 * @see #setTrafficClass(int) * @see StandardSocketOptions#IP_TOS @@ -1092,6 +1104,9 @@ public int getTrafficClass() throws SocketException { * *

If this socket has an associated channel then the channel is closed * as well. + * + *

Once closed, several of the methods defined by this class will throw + * an exception if invoked on the closed socket. */ public void close() { delegate().close(); @@ -1299,7 +1314,7 @@ public Set> supportedOptions() { * datagram packets, or {@code null}. * @throws IOException if there is an error joining, or when the address * is not a multicast address, or the platform does not support - * multicasting + * multicasting, or the socket is closed * @throws SecurityException if a security manager exists and its * {@code checkMulticast} method doesn't allow the join. * @throws IllegalArgumentException if mcastaddr is {@code null} or is a @@ -1343,7 +1358,7 @@ public void joinGroup(SocketAddress mcastaddr, NetworkInterface netIf) * is unspecified: any interface may be selected or the operation * may fail with a {@code SocketException}. * @throws IOException if there is an error leaving or when the address - * is not a multicast address. + * is not a multicast address, or the socket is closed. * @throws SecurityException if a security manager exists and its * {@code checkMulticast} method doesn't allow the operation. * @throws IllegalArgumentException if mcastaddr is {@code null} or is a diff --git a/src/java.base/share/classes/java/net/MulticastSocket.java b/src/java.base/share/classes/java/net/MulticastSocket.java index 9a9d57118c0f1..46757a6b4077e 100644 --- a/src/java.base/share/classes/java/net/MulticastSocket.java +++ b/src/java.base/share/classes/java/net/MulticastSocket.java @@ -221,7 +221,7 @@ public MulticastSocket(SocketAddress bindaddr) throws IOException { * * @param ttl the time-to-live * @throws IOException if an I/O exception occurs - * while setting the default time-to-live value + * while setting the default time-to-live value, or the socket is closed. * @deprecated use the {@link #setTimeToLive(int)} method instead, which uses * int instead of byte as the type for ttl. * @see #getTTL() @@ -250,7 +250,7 @@ public void setTTL(byte ttl) throws IOException { * * @throws IOException * if an I/O exception occurs while setting the - * default time-to-live value + * default time-to-live value, or the socket is closed. * * @see #getTimeToLive() * @see StandardSocketOptions#IP_MULTICAST_TTL @@ -265,7 +265,7 @@ public void setTimeToLive(int ttl) throws IOException { * the socket. * * @throws IOException if an I/O exception occurs - * while getting the default time-to-live value + * while getting the default time-to-live value, or the socket is closed. * @return the default time-to-live value * @deprecated use the {@link #getTimeToLive()} method instead, * which returns an int instead of a byte. @@ -285,7 +285,7 @@ public byte getTTL() throws IOException { * getOption(StandardSocketOptions.IP_MULTICAST_TTL)}. * * @throws IOException if an I/O exception occurs while - * getting the default time-to-live value + * getting the default time-to-live value, or the socket is closed. * @return the default time-to-live value * @see #setTimeToLive(int) * @see StandardSocketOptions#IP_MULTICAST_TTL @@ -311,7 +311,7 @@ public int getTimeToLive() throws IOException { * @param mcastaddr is the multicast address to join * @throws IOException if there is an error joining, * or when the address is not a multicast address, - * or the platform does not support multicasting + * or the platform does not support multicasting, or the socket is closed. * @throws SecurityException if a security manager exists and its * {@code checkMulticast} method doesn't allow the join. * @deprecated This method does not accept the network interface on @@ -339,7 +339,7 @@ public void joinGroup(InetAddress mcastaddr) throws IOException { * * @param mcastaddr is the multicast address to leave * @throws IOException if there is an error leaving - * or when the address is not a multicast address. + * or when the address is not a multicast address, or the socket is closed. * @throws SecurityException if a security manager exists and its * {@code checkMulticast} method doesn't allow the operation. * @deprecated This method does not accept the network interface on which @@ -393,7 +393,7 @@ public void leaveGroup(SocketAddress mcastaddr, NetworkInterface netIf) * * @param inf the InetAddress * @throws SocketException if there is an error in - * the underlying protocol, such as a TCP error. + * the underlying protocol, such as a TCP error, or the socket is closed. * @deprecated The InetAddress may not uniquely identify * the network interface. Use * {@link #setNetworkInterface(NetworkInterface)} instead. @@ -413,7 +413,7 @@ public void setInterface(InetAddress inf) throws SocketException { * or if no interface has been set, an {@code InetAddress} * representing any local address. * @throws SocketException if there is an error in the - * underlying protocol, such as a TCP error. + * underlying protocol, such as a TCP error, or the socket is closed. * @deprecated The network interface may not be uniquely identified by * the InetAddress returned. * Use {@link #getNetworkInterface()} instead. @@ -434,7 +434,7 @@ public InetAddress getInterface() throws SocketException { * * @param netIf the interface * @throws SocketException if there is an error in - * the underlying protocol, such as a TCP error. + * the underlying protocol, such as a TCP error, or the socket is closed. * @see #getNetworkInterface() * @see StandardSocketOptions#IP_MULTICAST_IF * @since 1.4 @@ -454,7 +454,7 @@ public void setNetworkInterface(NetworkInterface netIf) * getOption(StandardSocketOptions.IP_MULTICAST_IF)}. * * @throws SocketException if there is an error in - * the underlying protocol, such as a TCP error. + * the underlying protocol, such as a TCP error, or the socket is closed. * @return The multicast {@code NetworkInterface} currently set. A placeholder * NetworkInterface is returned when there is no interface set; it has * a single InetAddress to represent any local address. @@ -476,7 +476,8 @@ public NetworkInterface getNetworkInterface() throws SocketException { * verify what loopback mode is set to should call * {@link #getLoopbackMode()} * @param disable {@code true} to disable the LoopbackMode - * @throws SocketException if an error occurs while setting the value + * @throws SocketException if an error occurs while setting the value, or + * the socket is closed. * @since 1.4 * @deprecated Use {@link #setOption(SocketOption, Object)} with * {@link java.net.StandardSocketOptions#IP_MULTICAST_LOOP} @@ -493,7 +494,8 @@ public void setLoopbackMode(boolean disable) throws SocketException { /** * Get the setting for local loopback of multicast datagrams. * - * @throws SocketException if an error occurs while getting the value + * @throws SocketException if an error occurs while getting the value, or + * the socket is closed. * @return true if the LoopbackMode has been disabled * @since 1.4 * @deprecated Use {@link #getOption(SocketOption)} with @@ -534,8 +536,7 @@ public boolean getLoopbackMode() throws SocketException { * @param ttl optional time to live for multicast packet. * default ttl is 1. * - * @throws IOException is raised if an error occurs i.e - * error while setting ttl. + * @throws IOException if an I/O error occurs, or the socket is closed. * @throws SecurityException if a security manager exists and its * {@code checkMulticast} or {@code checkConnect} * method doesn't allow the send. diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/AbstractPoolEntry.java b/src/java.base/share/classes/jdk/internal/classfile/impl/AbstractPoolEntry.java index c6e6c4dce57a7..c27968eecab4f 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/AbstractPoolEntry.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/AbstractPoolEntry.java @@ -534,15 +534,6 @@ public Utf8Entry name() { public String asInternalName() { return ref1.stringValue(); } - - @Override - public boolean equals(Object o) { - if (o == this) { return true; } - if (o instanceof AbstractNamedEntry ne) { - return tag == ne.tag() && name().equals(ref1()); - } - return false; - } } public static final class ClassEntryImpl extends AbstractNamedEntry implements ClassEntry { diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/ChainedClassBuilder.java b/src/java.base/share/classes/jdk/internal/classfile/impl/ChainedClassBuilder.java index d31debf6f35a5..50c1590e8a271 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/ChainedClassBuilder.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/ChainedClassBuilder.java @@ -24,6 +24,7 @@ */ package jdk.internal.classfile.impl; +import java.lang.constant.MethodTypeDesc; import java.util.function.Consumer; import java.lang.classfile.*; @@ -78,6 +79,15 @@ public ClassBuilder withMethod(Utf8Entry name, Utf8Entry descriptor, int flags, return this; } + @Override + public ClassBuilder withMethod(String name, MethodTypeDesc descriptor, int flags, Consumer handler) { + var mb = new BufferedMethodBuilder(terminal.constantPool, terminal.context, + constantPool().utf8Entry(name), constantPool().utf8Entry(descriptor), flags, null); + mb.mDesc = descriptor; + consumer.accept(mb.run(handler).toModel()); + return this; + } + @Override public ClassBuilder transformMethod(MethodModel method, MethodTransform transform) { BufferedMethodBuilder builder = new BufferedMethodBuilder(terminal.constantPool, terminal.context, diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/DirectClassBuilder.java b/src/java.base/share/classes/jdk/internal/classfile/impl/DirectClassBuilder.java index 21fde0f6002df..0d61895fe9f7f 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/DirectClassBuilder.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/DirectClassBuilder.java @@ -26,6 +26,7 @@ package jdk.internal.classfile.impl; import java.lang.constant.ConstantDescs; +import java.lang.constant.MethodTypeDesc; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -106,6 +107,13 @@ public ClassBuilder withMethod(Utf8Entry name, .run(handler)); } + @Override + public ClassBuilder withMethod(String name, MethodTypeDesc descriptor, int flags, Consumer handler) { + var method = new DirectMethodBuilder(constantPool, context, constantPool.utf8Entry(name), constantPool.utf8Entry(descriptor), flags, null); + method.mDesc = descriptor; + return withMethod(method.run(handler)); + } + @Override public ClassBuilder transformMethod(MethodModel method, MethodTransform transform) { DirectMethodBuilder builder = new DirectMethodBuilder(constantPool, context, method.methodName(), diff --git a/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java b/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java index 06e79f416ac7a..5fac688b3115e 100644 --- a/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java +++ b/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java @@ -683,14 +683,12 @@ void blockingReceive(DatagramPacket p, long nanos) throws IOException { } long startNanos = System.nanoTime(); + long remainingNanos = nanos; SocketAddress sender = null; try { SocketAddress remote = beginRead(true, false); boolean connected = (remote != null); do { - long remainingNanos = (nanos > 0) - ? nanos - (System.nanoTime() - startNanos) - : 0; ByteBuffer dst = tryBlockingReceive(connected, bufLength, remainingNanos); // if datagram received then get sender and copy to DatagramPacket @@ -711,8 +709,8 @@ void blockingReceive(DatagramPacket p, long nanos) throws IOException { } } - // copy bytes to the DatagramPacket, and set length and sender if (sender != null) { + // copy bytes to the DatagramPacket, and set length and sender synchronized (p) { // re-read p.bufLength in case DatagramPacket changed int len = Math.min(dst.limit(), DatagramPackets.getBufLength(p)); @@ -720,6 +718,14 @@ void blockingReceive(DatagramPacket p, long nanos) throws IOException { DatagramPackets.setLength(p, len); p.setSocketAddress(sender); } + } else { + // need to retry, adjusting timeout if needed + if (nanos > 0) { + remainingNanos = nanos - (System.nanoTime() - startNanos); + if (remainingNanos <= 0) { + throw new SocketTimeoutException("Receive timed out"); + } + } } } finally { Util.offerFirstTemporaryDirectBuffer(dst); @@ -746,6 +752,7 @@ void blockingReceive(DatagramPacket p, long nanos) throws IOException { private ByteBuffer tryBlockingReceive(boolean connected, int len, long nanos) throws IOException { + assert nanos >= 0; long startNanos = System.nanoTime(); ByteBuffer dst = Util.getTemporaryDirectBuffer(len); int n = -1; diff --git a/src/java.desktop/share/classes/javax/swing/BoundedRangeModel.java b/src/java.desktop/share/classes/javax/swing/BoundedRangeModel.java index bc6a84ac89194..e6a9d08611dc6 100644 --- a/src/java.desktop/share/classes/javax/swing/BoundedRangeModel.java +++ b/src/java.desktop/share/classes/javax/swing/BoundedRangeModel.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ package javax.swing; -import javax.swing.event.*; +import javax.swing.event.ChangeListener; /** @@ -40,7 +40,7 @@ * range is value,value+extent. The inner range * must lie within the outer one, i.e. value must be * less than or equal to maximum and value+extent - * must greater than or equal to minimum, and maximum + * must be greater than or equal to minimum, and maximum * must be greater than or equal to minimum. * There are a few features of this model that one might find a little * surprising. These quirks exist for the convenience of the @@ -228,7 +228,7 @@ public interface BoundedRangeModel /** - * This method sets all of the model's data with a single method call. + * This method sets all the model's data with a single method call. * The method results in a single change event being generated. This is * convenient when you need to adjust all the model data simultaneously and * do not want individual change events to occur. diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicLookAndFeel.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicLookAndFeel.java index 999e7f923c744..4041bfca71435 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicLookAndFeel.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicLookAndFeel.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -727,6 +727,8 @@ public Object createValue(UIDefaults table) { "Button.highlight", controlLtHighlight, "Button.border", buttonBorder, "Button.margin", new InsetsUIResource(2, 14, 2, 14), + // The above margin has vastly larger horizontal values when + // compared to other look and feels that don't rely on these values "Button.textIconGap", 4, "Button.textShiftOffset", zero, "Button.focusInputMap", new UIDefaults.LazyInputMap(new Object[] { diff --git a/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalLookAndFeel.java b/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalLookAndFeel.java index 98747bbd2dc95..e46091c523cb6 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalLookAndFeel.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalLookAndFeel.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,28 +25,53 @@ package javax.swing.plaf.metal; -import java.awt.*; +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.Frame; +import java.awt.Insets; +import java.awt.Toolkit; +import java.awt.Window; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; -import javax.swing.plaf.*; -import javax.swing.*; -import javax.swing.plaf.basic.*; -import javax.swing.text.DefaultEditorKit; - -import java.awt.Color; import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; - import java.security.AccessController; -import sun.awt.*; +import javax.swing.ButtonModel; +import javax.swing.DefaultButtonModel; +import javax.swing.Icon; +import javax.swing.ImageIcon; +import javax.swing.JComponent; +import javax.swing.JDialog; +import javax.swing.JFrame; +import javax.swing.JRootPane; +import javax.swing.JTextField; +import javax.swing.JToggleButton; +import javax.swing.LayoutStyle; +import javax.swing.LookAndFeel; +import javax.swing.SwingConstants; +import javax.swing.SwingUtilities; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.plaf.BorderUIResource; +import javax.swing.plaf.ColorUIResource; +import javax.swing.plaf.FontUIResource; +import javax.swing.plaf.InsetsUIResource; +import javax.swing.plaf.UIResource; +import javax.swing.plaf.basic.BasicLookAndFeel; +import javax.swing.text.DefaultEditorKit; + +import sun.awt.AppContext; +import sun.awt.OSInfo; +import sun.awt.SunToolkit; import sun.security.action.GetPropertyAction; import sun.swing.DefaultLayoutStyle; -import static javax.swing.UIDefaults.LazyValue; - import sun.swing.SwingAccessor; import sun.swing.SwingUtilities2; +import static javax.swing.UIDefaults.LazyValue; + /** * The Java Look and Feel, otherwise known as Metal. *

@@ -782,6 +807,8 @@ protected void initComponentDefaults(UIDefaults table) { "SPACE", "pressed", "released SPACE", "released" }), + // Button default margin is (2, 14, 2, 14), defined in + // BasicLookAndFeel via "Button.margin" UI property. "CheckBox.disabledText", inactiveControlTextColor, "Checkbox.select", controlShadow, diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/Exchange.java b/src/java.net.http/share/classes/jdk/internal/net/http/Exchange.java index e643b05422afd..eb30dc85e9c8e 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/Exchange.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/Exchange.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, 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 @@ -39,6 +39,8 @@ import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import java.util.function.Function; import java.net.http.HttpClient; import java.net.http.HttpHeaders; @@ -453,32 +455,55 @@ private CompletableFuture checkFor407(ExchangeImpl ex, Throwable t, // for the 100-Continue response private CompletableFuture expectContinue(ExchangeImpl ex) { assert request.expectContinue(); + + long responseTimeoutMillis = 5000; + if (request.timeout().isPresent()) { + final long timeoutMillis = request.timeout().get().toMillis(); + responseTimeoutMillis = Math.min(responseTimeoutMillis, timeoutMillis); + } + return ex.getResponseAsync(parentExecutor) + .completeOnTimeout(null, responseTimeoutMillis, TimeUnit.MILLISECONDS) .thenCompose((Response r1) -> { - Log.logResponse(r1::toString); - int rcode = r1.statusCode(); - if (rcode == 100) { - Log.logTrace("Received 100-Continue: sending body"); - if (debug.on()) debug.log("Received 100-Continue for %s", r1); - CompletableFuture cf = - exchImpl.sendBodyAsync() - .thenCompose(exIm -> exIm.getResponseAsync(parentExecutor)); - cf = wrapForUpgrade(cf); - cf = wrapForLog(cf); - return cf; - } else { - Log.logTrace("Expectation failed: Received {0}", - rcode); - if (debug.on()) debug.log("Expect-Continue failed (%d) for: %s", rcode, r1); - if (upgrading && rcode == 101) { - IOException failed = new IOException( - "Unable to handle 101 while waiting for 100"); - return MinimalFuture.failedFuture(failed); - } - exchImpl.expectContinueFailed(rcode); - return MinimalFuture.completedFuture(r1); - } - }); + // The response will only be null if there was a timeout + // send body regardless + if (r1 == null) { + if (debug.on()) + debug.log("Setting ExpectTimeoutRaised and sending request body"); + exchImpl.setExpectTimeoutRaised(); + CompletableFuture cf = + exchImpl.sendBodyAsync() + .thenCompose(exIm -> exIm.getResponseAsync(parentExecutor)); + cf = wrapForUpgrade(cf); + cf = wrapForLog(cf); + return cf; + } + + Log.logResponse(r1::toString); + int rcode = r1.statusCode(); + if (rcode == 100) { + Log.logTrace("Received 100-Continue: sending body"); + if (debug.on()) + debug.log("Received 100-Continue for %s", r1); + CompletableFuture cf = + exchImpl.sendBodyAsync() + .thenCompose(exIm -> exIm.getResponseAsync(parentExecutor)); + cf = wrapForUpgrade(cf); + cf = wrapForLog(cf); + return cf; + } else { + Log.logTrace("Expectation failed: Received {0}", rcode); + if (debug.on()) + debug.log("Expect-Continue failed (%d) for: %s", rcode, r1); + if (upgrading && rcode == 101) { + IOException failed = new IOException( + "Unable to handle 101 while waiting for 100"); + return MinimalFuture.failedFuture(failed); + } + exchImpl.expectContinueFailed(rcode); + return MinimalFuture.completedFuture(r1); + } + }); } // After sending the request headers, if no ProxyAuthorizationRequired diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/ExchangeImpl.java b/src/java.net.http/share/classes/jdk/internal/net/http/ExchangeImpl.java index 404f970cc59ef..f393b021cd436 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/ExchangeImpl.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/ExchangeImpl.java @@ -58,6 +58,8 @@ abstract class ExchangeImpl { final Exchange exchange; + private volatile boolean expectTimeoutRaised; + // this will be set to true only when the peer explicitly states (through a GOAWAY frame or // a relevant error code in reset frame) that the corresponding stream (id) wasn't processed private volatile boolean unprocessedByPeer; @@ -71,6 +73,14 @@ final Exchange getExchange() { return exchange; } + final void setExpectTimeoutRaised() { + expectTimeoutRaised = true; + } + + final boolean expectTimeoutRaised() { + return expectTimeoutRaised; + } + HttpClientImpl client() { return exchange.client(); } diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/Stream.java b/src/java.net.http/share/classes/jdk/internal/net/http/Stream.java index 1a007e82adcdc..4563362292329 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/Stream.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/Stream.java @@ -1200,11 +1200,17 @@ CompletableFuture getResponseAsync(Executor executor) { try { if (!response_cfs.isEmpty()) { // This CompletableFuture was created by completeResponse(). - // it will be already completed. - cf = response_cfs.remove(0); + // it will be already completed, unless the expect continue + // timeout fired + cf = response_cfs.get(0); + if (cf.isDone()) { + cf = response_cfs.remove(0); + } + // if we find a cf here it should be already completed. // finding a non completed cf should not happen. just assert it. - assert cf.isDone() : "Removing uncompleted response: could cause code to hang!"; + assert cf.isDone() || request.expectContinue && expectTimeoutRaised() + : "Removing uncompleted response: could cause code to hang!"; } else { // getResponseAsync() is called first. Create a CompletableFuture // that will be completed by completeResponse() when @@ -1239,7 +1245,7 @@ void completeResponse(Response resp) { int cfs_len = response_cfs.size(); for (int i=0; i flags, DocPath fileName, TypeElement typeElement, + Element previewTarget, ExecutableElement restrictedTarget) { Content spacer = Text.EMPTY; if (flags.contains(ElementFlag.PREVIEW)) { - link.add(HtmlTree.SUP(m_writer.contents.previewMark)); + content.add(HtmlTree.SUP(getSuperscript(fileName, typeElement, + m_writer.htmlIds.forPreviewSection(previewTarget), + m_writer.contents.previewMark))); spacer = Entity.NO_BREAK_SPACE; } if (flags.contains(ElementFlag.RESTRICTED)) { - link.add(spacer); - link.add(HtmlTree.SUP(m_writer.contents.restrictedMark)); + content.add(spacer); + content.add(HtmlTree.SUP(getSuperscript(fileName, typeElement, + m_writer.htmlIds.forRestrictedSection(restrictedTarget), + m_writer.contents.restrictedMark))); + } + } + + /** + * Returns PREVIEW or RESTRICTED superscript as either local or external link or as plain text. + * + * @param fileName local file name to link to, or null if no local link target + * @param typeElement external type to link to, or null if no external link + * @param id the id fragment to link to + * @param label the label content + * @return superscript content + */ + private Content getSuperscript(DocPath fileName, TypeElement typeElement, HtmlId id, Content label) { + if (fileName != null) { + return m_writer.links.createLink(fileName.fragment(id.name()), label); + } else if (typeElement != null) { + return (m_writer.getCrossClassLink(typeElement, id.name(), label, null, false)); + } else { + return label; } - return link; } /** diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/script.js.template b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/script.js.template index 71ef847670822..633f453bc43b1 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/script.js.template +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/script.js.template @@ -461,7 +461,7 @@ document.addEventListener("DOMContentLoaded", function(e) { }) } // Resize handler - function handleResize(e) { + new ResizeObserver((entries) => { if (expanded) { if (windowWidth !== window.innerWidth) { collapse(); @@ -475,7 +475,5 @@ document.addEventListener("DOMContentLoaded", function(e) { handleScroll(); } setTopMargin(); - } - window.addEventListener("orientationchange", handleResize); - window.addEventListener("resize", handleResize); + }).observe(document.body); }); diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/taglets/LinkTaglet.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/taglets/LinkTaglet.java index b16a1490b6303..15e88da5baeb5 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/taglets/LinkTaglet.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/taglets/LinkTaglet.java @@ -224,6 +224,7 @@ Content linkSeeReferenceOutput(Element holder, labelContent = plainOrCode(isPlain, Text.of(utils.getSimpleName(refClass))); } return htmlWriter.getLink(new HtmlLinkInfo(config, HtmlLinkInfo.Kind.PLAIN, refClass) + .skipPreview(isPlain) .label(labelContent)); } else if (refMem == null) { // This is a fragment reference since refClass and refFragment are not null but refMem is null. diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 6cde711138310..bbf594f3bc70b 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -743,6 +743,7 @@ jdk/incubator/vector/LoadJsvmlTest.java 8305390 windows- # jdk_jfr +jdk/jfr/event/compiler/TestCodeSweeper.java 8338127 generic-all jdk/jfr/event/runtime/TestResidentSetSizeEvent.java 8309846 aix-ppc64 jdk/jfr/jvm/TestWaste.java 8282427 generic-all diff --git a/test/jdk/java/lang/management/ClassLoadingMXBean/TestVerboseClassLoading.java b/test/jdk/java/lang/management/ClassLoadingMXBean/TestVerboseClassLoading.java new file mode 100644 index 0000000000000..4e865f24b2901 --- /dev/null +++ b/test/jdk/java/lang/management/ClassLoadingMXBean/TestVerboseClassLoading.java @@ -0,0 +1,84 @@ +/* + * 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 8338139 + * @summary Basic unit test of ClassLoadingMXBean.set/isVerbose() when + * related unified logging is enabled. + * + * @run main/othervm -Xlog:class+load=trace:file=vm.log TestVerboseClassLoading false + * @run main/othervm -Xlog:class+load=debug:file=vm.log TestVerboseClassLoading false + * @run main/othervm -Xlog:class+load=info:file=vm.log TestVerboseClassLoading false + * + * @run main/othervm -Xlog:class+load=trace TestVerboseClassLoading false + * @run main/othervm -Xlog:class+load=debug TestVerboseClassLoading false + * @run main/othervm -Xlog:class+load=info TestVerboseClassLoading false + * @run main/othervm -Xlog:class+load=warning TestVerboseClassLoading false + * @run main/othervm -Xlog:class+load=error TestVerboseClassLoading false + * @run main/othervm -Xlog:class+load=off TestVerboseClassLoading false + * + * @run main/othervm -Xlog:class+load*=trace TestVerboseClassLoading true + * @run main/othervm -Xlog:class+load*=debug TestVerboseClassLoading true + * @run main/othervm -Xlog:class+load*=info TestVerboseClassLoading true + * @run main/othervm -Xlog:class+load*=warning TestVerboseClassLoading false + * @run main/othervm -Xlog:class+load*=error TestVerboseClassLoading false + * @run main/othervm -Xlog:class+load*=off TestVerboseClassLoading false + * + * @run main/othervm -Xlog:class+load*=info,class+load+cause=trace TestVerboseClassLoading true + * @run main/othervm -Xlog:class+load*=info,class+load+cause=debug TestVerboseClassLoading true + * @run main/othervm -Xlog:class+load*=info,class+load+cause=info TestVerboseClassLoading true + * @run main/othervm -Xlog:class+load*=info,class+load+cause=warning TestVerboseClassLoading false + * @run main/othervm -Xlog:class+load*=info,class+load+cause=error TestVerboseClassLoading false + * @run main/othervm -Xlog:class+load*=info,class+load+cause=off TestVerboseClassLoading false + * + * @run main/othervm -Xlog:all=trace:file=vm.log TestVerboseClassLoading false + */ + +import java.lang.management.ManagementFactory; +import java.lang.management.ClassLoadingMXBean; + +public class TestVerboseClassLoading { + + public static void main(String[] args) throws Exception { + ClassLoadingMXBean mxBean = ManagementFactory.getClassLoadingMXBean(); + boolean expected = Boolean.parseBoolean(args[0]); + boolean initial = mxBean.isVerbose(); + if (expected != initial) { + throw new Error("Initial verbosity setting was unexpectedly " + initial); + } + mxBean.setVerbose(false); + if (mxBean.isVerbose()) { + throw new Error("Verbosity was still enabled"); + } + mxBean.setVerbose(true); + if (!mxBean.isVerbose()) { + throw new Error("Verbosity was still disabled"); + } + // Turn off again as a double-check and also to avoid excessive logging + mxBean.setVerbose(false); + if (mxBean.isVerbose()) { + throw new Error("Verbosity was still enabled"); + } + } +} diff --git a/test/jdk/java/lang/management/MemoryMXBean/TestVerboseMemory.java b/test/jdk/java/lang/management/MemoryMXBean/TestVerboseMemory.java new file mode 100644 index 0000000000000..7d34c45036b18 --- /dev/null +++ b/test/jdk/java/lang/management/MemoryMXBean/TestVerboseMemory.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8338139 + * @summary Basic unit test of TestVerboseMemory.set/isVerbose() when + * related unified logging is enabled. + * + * @run main/othervm -Xlog:gc=trace:file=vm.log TestVerboseMemory false + * @run main/othervm -Xlog:gc=debug:file=vm.log TestVerboseMemory false + * @run main/othervm -Xlog:gc=info:file=vm.log TestVerboseMemory false + * + * @run main/othervm -Xlog:gc=off TestVerboseMemory false + * @run main/othervm -Xlog:gc=error TestVerboseMemory false + * @run main/othervm -Xlog:gc=warning TestVerboseMemory false + * + * @run main/othervm -Xlog:gc=info TestVerboseMemory true + * @run main/othervm -Xlog:gc=trace TestVerboseMemory true + * @run main/othervm -Xlog:gc=debug TestVerboseMemory true + * + * @run main/othervm -Xlog:gc*=info TestVerboseMemory true + * @run main/othervm -Xlog:gc*=debug TestVerboseMemory true + * @run main/othervm -Xlog:gc*=trace TestVerboseMemory true + * + * @run main/othervm -Xlog:gc=info,gc+init=off TestVerboseMemory true + * @run main/othervm -Xlog:gc=off,gc+init=info TestVerboseMemory false + * @run main/othervm -Xlog:gc,gc+init TestVerboseMemory true + * + * @run main/othervm -Xlog:all=trace:file=vm.log TestVerboseMemory false + */ + +import java.lang.management.ManagementFactory; +import java.lang.management.MemoryMXBean; + +public class TestVerboseMemory { + + public static void main(String[] args) throws Exception { + MemoryMXBean mxBean = ManagementFactory.getMemoryMXBean(); + boolean expected = Boolean.parseBoolean(args[0]); + boolean initial = mxBean.isVerbose(); + if (expected != initial) { + throw new Error("Initial verbosity setting was unexpectedly " + initial); + } + mxBean.setVerbose(false); + if (mxBean.isVerbose()) { + throw new Error("Verbosity was still enabled"); + } + mxBean.setVerbose(true); + if (!mxBean.isVerbose()) { + throw new Error("Verbosity was still disabled"); + } + // Turn off again as a double-check and also to avoid excessive logging + mxBean.setVerbose(false); + if (mxBean.isVerbose()) { + throw new Error("Verbosity was still enabled"); + } + } +} diff --git a/test/jdk/java/net/httpclient/ExpectContinueTest.java b/test/jdk/java/net/httpclient/ExpectContinueTest.java index 2996d6e252b57..3d28ae8c8b49c 100644 --- a/test/jdk/java/net/httpclient/ExpectContinueTest.java +++ b/test/jdk/java/net/httpclient/ExpectContinueTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -85,8 +85,8 @@ public class ExpectContinueTest implements HttpServerAdapters { Http1HangServer http1HangServer; Http2TestServer http2TestServer; // HTTP/2 - URI getUri, postUri, hangUri; - URI h2postUri, h2hangUri, h2endStreamUri, h2warmupURI; + URI getUri, postUri, forcePostUri, hangUri; + URI h2postUri, h2forcePostUri, h2hangUri, h2endStreamUri, h2warmupURI; static PrintStream err = new PrintStream(System.err); static PrintStream out = new PrintStream(System.out); @@ -97,8 +97,10 @@ public Object[][] urisData() { return new Object[][]{ // URI, Expected Status Code, Will finish with Exception, Protocol Version { postUri, 200, false, HTTP_1_1 }, + { forcePostUri, 200, false, HTTP_1_1 }, { hangUri, 417, false, HTTP_1_1}, { h2postUri, 200, false, HTTP_2 }, + { h2forcePostUri, 200, false, HTTP_2 }, { h2hangUri, 417, false, HTTP_2 }, { h2endStreamUri, 200, true, HTTP_2 }, // Error }; @@ -127,7 +129,7 @@ public void test(URI uri, int expectedStatusCode, boolean exceptionally, HttpCli } catch (Exception e) { testThrowable = e.getCause(); } - verifyRequest(expectedStatusCode, resp, exceptionally, testThrowable); + verifyRequest(uri.getPath(), expectedStatusCode, resp, exceptionally, testThrowable); } } @@ -137,8 +139,10 @@ public void setup() throws Exception { http1TestServer = HttpTestServer.create(HTTP_1_1); http1TestServer.addHandler(new GetHandler(), "/http1/get"); http1TestServer.addHandler(new PostHandler(), "/http1/post"); + http1TestServer.addHandler(new ForcePostHandler(), "/http1/forcePost"); getUri = URI.create("http://" + http1TestServer.serverAuthority() + "/http1/get"); postUri = URI.create("http://" + http1TestServer.serverAuthority() + "/http1/post"); + forcePostUri = URI.create("http://" + http1TestServer.serverAuthority() + "/http1/forcePost"); // Due to limitations of the above Http1 Test Server, a manual approach is taken to test the hanging with the // httpclient using Http1 so that the correct response header can be returned for the test case @@ -149,17 +153,19 @@ public void setup() throws Exception { http2TestServer.setExchangeSupplier(ExpectContinueTestExchangeImpl::new); http2TestServer.addHandler(new GetHandler().toHttp2Handler(), "/http2/warmup"); http2TestServer.addHandler(new PostHandler().toHttp2Handler(), "/http2/post"); + http2TestServer.addHandler(new ForcePostHandler().toHttp2Handler(), "/http2/forcePost"); http2TestServer.addHandler(new PostHandlerCantContinue().toHttp2Handler(), "/http2/hang"); http2TestServer.addHandler(new PostHandlerHttp2(), "/http2/endStream"); h2warmupURI = new URI("http://" + http2TestServer.serverAuthority() + "/http2/warmup"); h2postUri = URI.create("http://" + http2TestServer.serverAuthority() + "/http2/post"); + h2forcePostUri = URI.create("http://" + http2TestServer.serverAuthority() + "/http2/forcePost"); h2hangUri = URI.create("http://" + http2TestServer.serverAuthority() + "/http2/hang"); h2endStreamUri = URI.create("http://" + http2TestServer.serverAuthority() + "/http2/endStream"); - out.printf("HTTP/1.1 server listening at: %s", http1TestServer.serverAuthority()); - out.printf("HTTP/1.1 hang server listening at: %s", hangUri.getRawAuthority()); - out.printf("HTTP/2 clear server listening at: %s", http2TestServer.serverAuthority()); + out.printf("HTTP/1.1 server listening at: %s %n", http1TestServer.serverAuthority()); + out.printf("HTTP/1.1 hang server listening at: %s %n", hangUri.getRawAuthority()); + out.printf("HTTP/2 clear server listening at: %s %n", http2TestServer.serverAuthority()); http1TestServer.start(); http1HangServer.start(); @@ -207,6 +213,18 @@ public void handle(HttpTestExchange exchange) throws IOException { } } + static class ForcePostHandler implements HttpTestHandler { + @Override + public void handle(HttpTestExchange exchange) throws IOException { + try (InputStream is = exchange.getRequestBody()) { + err.println("Server reading body inside the force Post"); + is.readAllBytes(); + err.println("Server send 200 (length=0) in the force post"); + exchange.sendResponseHeaders(200, 0); + } + } + } + static class PostHandlerHttp2 implements Http2Handler { @Override @@ -337,15 +355,18 @@ public void close() throws IOException { } } - private void verifyRequest(int expectedStatusCode, HttpResponse resp, boolean exceptionally, Throwable testThrowable) { + private void verifyRequest(String path, int expectedStatusCode, HttpResponse resp, boolean exceptionally, Throwable testThrowable) { + if (!exceptionally) { + err.printf("Response code %s received for path %s %n", resp.statusCode(), path); + } if (exceptionally && testThrowable != null) { - err.println(testThrowable); + err.println("Finished exceptionally Test throwable: " + testThrowable); assertEquals(IOException.class, testThrowable.getClass()); } else if (exceptionally) { throw new TestException("Expected case to finish with an IOException but testException is null"); } else if (resp != null) { assertEquals(resp.statusCode(), expectedStatusCode); - err.println("Request completed successfully"); + err.println("Request completed successfully for path " + path); err.println("Response Headers: " + resp.headers()); err.println("Response Status Code: " + resp.statusCode()); } diff --git a/test/jdk/java/nio/channels/DatagramChannel/AdaptorMulticasting.java b/test/jdk/java/nio/channels/DatagramChannel/AdaptorMulticasting.java index 0c8da1ff9d9c9..cab2bc7628562 100644 --- a/test/jdk/java/nio/channels/DatagramChannel/AdaptorMulticasting.java +++ b/test/jdk/java/nio/channels/DatagramChannel/AdaptorMulticasting.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -48,6 +48,7 @@ import java.util.stream.Collectors; import static java.net.StandardSocketOptions.*; import static java.net.StandardProtocolFamily.*; +import static jdk.test.lib.NetworkConfiguration.isSameInterface; import jdk.test.lib.NetworkConfiguration; import jdk.test.lib.net.IPSupport; @@ -295,8 +296,8 @@ static void testNetworkInterface(MulticastSocket s, // setNetworkInterface s.setNetworkInterface(ni); - assertTrue(s.getNetworkInterface().equals(ni)); - assertTrue(s.getOption(IP_MULTICAST_IF).equals(ni)); + assertTrue(isSameInterface(s.getNetworkInterface(), ni)); + assertTrue(isSameInterface(s.getOption(IP_MULTICAST_IF), ni)); InetAddress address = s.getInterface(); assertTrue(ni.inetAddresses().filter(address::equals).findAny().isPresent()); @@ -315,8 +316,8 @@ static void testNetworkInterface(MulticastSocket s, // setOption(IP_MULTICAST_IF) s.setOption(IP_MULTICAST_IF, ni); - assertTrue(s.getOption(IP_MULTICAST_IF).equals(ni)); - assertTrue(s.getNetworkInterface().equals(ni)); + assertTrue(isSameInterface(s.getOption(IP_MULTICAST_IF), ni)); + assertTrue(isSameInterface(s.getNetworkInterface(), ni)); // bad values for IP_MULTICAST_IF assertThrows(IllegalArgumentException.class, @@ -412,7 +413,8 @@ static void testSendReceive(MulticastSocket s, InetAddress group) throws IOExcep assertTrue(s.getOption(IP_MULTICAST_IF) != null); SocketAddress target = new InetSocketAddress(group, s.getLocalPort()); - byte[] message = "hello".getBytes("UTF-8"); + String msg = "AdaptorMulticasting: " + System.nanoTime(); + byte[] message = msg.getBytes("UTF-8"); // send message to multicast group DatagramPacket p = new DatagramPacket(message, message.length); @@ -421,8 +423,22 @@ static void testSendReceive(MulticastSocket s, InetAddress group) throws IOExcep // receive message s.setSoTimeout(0); - p = new DatagramPacket(new byte[1024], 100); - s.receive(p); + while (true) { + p = new DatagramPacket(new byte[1024], 100); + s.receive(p); + if (p.getPort() == s.getLocalPort()) { + String str = new String(p.getData(), p.getOffset(), p.getLength(), "UTF-8"); + if (Arrays.equals(p.getData(), p.getOffset(), p.getLength(), message, 0, message.length)) { + System.out.format("Got expected message \"%s\" from %s%n", str, p.getSocketAddress()); + break; + } + System.out.println("Unexpected message received. Expected: " + msg); + System.out.println("Received message doesn't match - skipping: " + str); + } else { + System.out.println("Unexpected message received. Expected message from: " + s.getLocalAddress()); + System.out.println("Received message sender doesn't match - skipping: " + p.getSocketAddress()); + } + } assertTrue(p.getLength() == message.length); assertTrue(p.getPort() == s.getLocalPort()); diff --git a/test/jdk/java/nio/channels/DatagramChannel/AfterDisconnect.java b/test/jdk/java/nio/channels/DatagramChannel/AfterDisconnect.java index 6a80d686b305b..de59984dae15f 100644 --- a/test/jdk/java/nio/channels/DatagramChannel/AfterDisconnect.java +++ b/test/jdk/java/nio/channels/DatagramChannel/AfterDisconnect.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,6 +31,7 @@ */ import java.io.IOException; +import java.net.BindException; import java.net.InetAddress; import java.net.Inet6Address; import java.net.InetSocketAddress; @@ -46,6 +47,7 @@ import java.nio.channels.Selector; import java.util.HashMap; import java.util.Map; +import java.util.function.Predicate; import org.testng.annotations.Test; import static org.testng.Assert.*; @@ -54,6 +56,38 @@ public class AfterDisconnect { + interface RetryableTest { + public void runTest() throws T; + } + + // retry the given lambda (RetryableTest) if an exception + // that satisfies the predicate (retryOn) is caught. + void testWithRetry(RetryableTest test, + Predicate retryOn, + int max) throws T { + for (int i=0; i < max; i++) { + try { + test.runTest(); + break; + } catch (Throwable t) { + if (i < max -1 && retryOn.test(t)) { + System.out.println("Got " + t + "; will retry"); + } else throw t; + } + } + } + + /** + * When calling {@link DatagramChannel#disconnect()} a {@link BindException} + * may occur. In which case we want to retry the test. + */ + class BindExceptionOnDisconnect extends BindException { + BindExceptionOnDisconnect(BindException x) { + super(x.getMessage()); + initCause(x); + } + } + @Test public void execute() throws IOException { IPSupport.throwSkippedExceptionIfNonOperational(); @@ -61,34 +95,41 @@ public void execute() throws IOException { InetAddress lb = InetAddress.getLoopbackAddress(); // test with default protocol family - try (DatagramChannel dc = DatagramChannel.open()) { - System.out.println("Test with default"); - dc.bind(new InetSocketAddress(lb, 0)); - test(dc); - test(dc); - } - - // test with IPv6 socket - if (IPSupport.hasIPv6()) { - System.out.println("Test with IPv6 socket"); - try (DatagramChannel dc = DatagramChannel.open(StandardProtocolFamily.INET6)) { + System.out.println("Test with default"); + testWithRetry(() -> { + try (DatagramChannel dc = DatagramChannel.open()) { dc.bind(new InetSocketAddress(lb, 0)); test(dc); test(dc); } + }, BindExceptionOnDisconnect.class::isInstance, 5); + + // test with IPv6 socket + if (IPSupport.hasIPv6()) { + System.out.println("Test with IPv6 socket"); + testWithRetry(() -> { + try (DatagramChannel dc = DatagramChannel.open(StandardProtocolFamily.INET6)) { + dc.bind(new InetSocketAddress(lb, 0)); + test(dc); + test(dc); + } + }, BindExceptionOnDisconnect.class::isInstance, 5); } // test with IPv4 socket if (IPSupport.hasIPv4() && !preferIPv6) { System.out.println("Test with IPv4 socket"); - try (DatagramChannel dc = DatagramChannel.open(StandardProtocolFamily.INET)) { - dc.bind(new InetSocketAddress(lb, 0)); - test(dc); - test(dc); - } + testWithRetry(() -> { + try (DatagramChannel dc = DatagramChannel.open(StandardProtocolFamily.INET)) { + dc.bind(new InetSocketAddress(lb, 0)); + test(dc); + test(dc); + } + }, BindExceptionOnDisconnect.class::isInstance, 5); } } + void test(DatagramChannel dc) throws IOException { testLocalAddress(dc); testSocketOptions(dc); @@ -111,7 +152,11 @@ void testLocalAddress(DatagramChannel dc) throws IOException { assertEquals(dc.getLocalAddress(), local); assertEquals(dc.getRemoteAddress(), remote); - dc.disconnect(); + try { + dc.disconnect(); + } catch (BindException x) { + throw new BindExceptionOnDisconnect(x); + } assertFalse(dc.isConnected()); assertEquals(dc.getLocalAddress(), local); assertTrue(dc.getRemoteAddress() == null); @@ -134,7 +179,11 @@ void testSocketOptions(DatagramChannel dc) throws IOException { Map, Object> map = options(dc); dc.connect(dc.getLocalAddress()); - dc.disconnect(); + try { + dc.disconnect(); + } catch (BindException x) { + throw new BindExceptionOnDisconnect(x); + } // check socket options have not changed assertEquals(map, options(dc)); @@ -168,7 +217,11 @@ void testSelectorRegistration(DatagramChannel dc) throws IOException { sel.selectNow(); dc.connect(dc.getLocalAddress()); - dc.disconnect(); + try { + dc.disconnect(); + } catch (BindException x) { + throw new BindExceptionOnDisconnect(x); + } // selection key should still be valid assertTrue(key.isValid()); @@ -210,7 +263,11 @@ void testMulticastGroups(DatagramChannel dc) throws IOException { MembershipKey key = dc.join(group, ni); dc.connect(dc.getLocalAddress()); - dc.disconnect(); + try { + dc.disconnect(); + } catch (BindException x) { + throw new BindExceptionOnDisconnect(x); + } // membership key should still be valid assertTrue(key.isValid()); diff --git a/test/jdk/java/nio/channels/DatagramChannel/Connect.java b/test/jdk/java/nio/channels/DatagramChannel/Connect.java index 082a3234cc5a7..41c172b33284d 100644 --- a/test/jdk/java/nio/channels/DatagramChannel/Connect.java +++ b/test/jdk/java/nio/channels/DatagramChannel/Connect.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2023, 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 @@ -23,6 +23,8 @@ /* @test * @bug 4313882 7183800 + * @library /test/lib + * @build jdk.test.lib.Platform Connect * @run main/othervm Connect * @summary Test DatagramChannel's send and receive methods */ @@ -38,6 +40,8 @@ import java.util.concurrent.CompletionException; import java.util.stream.Stream; +import jdk.test.lib.Platform; + import static java.nio.charset.StandardCharsets.US_ASCII; public class Connect { @@ -114,9 +118,21 @@ public void run() { ByteBuffer bb = ByteBuffer.allocateDirect(MAX); bb.put(bytes); bb.flip(); + // When connecting an unbound datagram channel, the underlying + // socket will first be bound to the wildcard address. On macOS, + // the system may allocate the same port on which another socket + // is already bound with a more specific address. This may prevent + // datagrams directed at the connected socket to reach it. + // To avoid this, when on macOS, we preemptively bind `dc` to the + // specific address instead of letting it bind to the wildcard. + if (Platform.isOSX()) { + dc.bind(new InetSocketAddress(((InetSocketAddress)connectSocketAddress).getAddress(), 0)); + err.println("Initiator bound to: " + connectSocketAddress); + } err.println("Initiator connecting to: " + connectSocketAddress); dc.connect(connectSocketAddress); err.println("Initiator bound to: " + dc.getLocalAddress()); + assert !connectSocketAddress.equals(dc.getLocalAddress()); // Send a message err.println("Initiator attempting to write to Responder at " + connectSocketAddress); diff --git a/test/jdk/java/nio/channels/DatagramChannel/ManySourcesAndTargets.java b/test/jdk/java/nio/channels/DatagramChannel/ManySourcesAndTargets.java index ed4e9c0c02e04..18a18fcba0a38 100644 --- a/test/jdk/java/nio/channels/DatagramChannel/ManySourcesAndTargets.java +++ b/test/jdk/java/nio/channels/DatagramChannel/ManySourcesAndTargets.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /* @test * @bug 8234805 8235193 * @summary Test DatagramChannel send/receive and that receive returns the expected - * sender address + * sender address. * @run main/othervm ManySourcesAndTargets * @run main/othervm -Djava.net.preferIPv4Stack=true ManySourcesAndTargets */ @@ -63,6 +63,7 @@ public static void main(String[] args) throws Exception { try (DatagramChannel reader = DatagramChannel.open()) { // bind reader to wildcard address so it can receive from any address reader.bind(new InetSocketAddress(0)); + System.out.println("\nReader bound to: " + reader.getLocalAddress()); for (InetAddress address : addresses) { System.out.format("%n-- %s --%n", address.getHostAddress()); @@ -75,6 +76,7 @@ public static void main(String[] args) throws Exception { try (DatagramChannel sender = DatagramChannel.open()) { // bind sender to wildcard address so it can send to any address sender.bind(new InetSocketAddress(0)); + System.out.println("\nSender bound to: " + sender.getLocalAddress()); for (InetAddress address : addresses) { System.out.format("%n-- %s --%n", address.getHostAddress()); @@ -97,6 +99,11 @@ static void testSend(int count, InetAddress address, DatagramChannel reader) thr sender.bind(new InetSocketAddress(address, 0)); SocketAddress local = sender.getLocalAddress(); + System.out.println("Sender bound to: " + local); + if (((InetSocketAddress)local).getPort() == remotePort) { + System.out.println("testSend: Sender and reader have same port: skipping"); + return; + } byte[] bytes = serialize(local); SocketAddress previousSource = null; @@ -105,6 +112,8 @@ static void testSend(int count, InetAddress address, DatagramChannel reader) thr sender.send(ByteBuffer.wrap(bytes), remote); ByteBuffer bb = ByteBuffer.allocate(1000); + System.out.format("testSend: reader waiting to receive at: %s%n", + reader.getLocalAddress()); SocketAddress source = reader.receive(bb); System.out.format("received datagram from %s%n", source); @@ -138,11 +147,18 @@ static void testReceive(int count, DatagramChannel sender, InetAddress address) SocketAddress remote = reader.getLocalAddress(); + System.out.println("Reader bound to: " + remote); + if (((InetSocketAddress)local).getPort() == ((InetSocketAddress)remote).getPort()) { + System.out.println("testReceive: Sender and reader have same port: skipping"); + return; + } for (int i = 0; i < count; i++) { System.out.format("send %s -> %s%n", local, remote); sender.send(ByteBuffer.allocate(32), remote); ByteBuffer bb = ByteBuffer.allocate(1000); + System.out.format("testReceive: reader waiting to receive at: %s%n", + reader.getLocalAddress()); SocketAddress source = reader.receive(bb); System.out.format("received datagram from %s%n", source); } @@ -165,7 +181,12 @@ private static SocketAddress deserialize(byte[] bytes) throws Exception { private static Optional networkInterface(InetAddress ia) { try { - return Optional.ofNullable(NetworkInterface.getByInetAddress(ia)); + NetworkInterface nif = NetworkInterface.getByInetAddress(ia); + if (nif != null) { + System.out.format("Selecting interface %s[%d]%n\twith addresses:%n\t%s%n", + nif.getDisplayName(), nif.getIndex(), nif.inetAddresses().toList()); + } + return Optional.ofNullable(nif); } catch (SocketException e) { return Optional.empty(); } diff --git a/test/jdk/java/nio/channels/DatagramChannel/MulticastSendReceiveTests.java b/test/jdk/java/nio/channels/DatagramChannel/MulticastSendReceiveTests.java index c1ea04ba2160d..87aedc8efd91a 100644 --- a/test/jdk/java/nio/channels/DatagramChannel/MulticastSendReceiveTests.java +++ b/test/jdk/java/nio/channels/DatagramChannel/MulticastSendReceiveTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -99,15 +99,25 @@ static void receiveDatagram(DatagramChannel dc, ByteBuffer buf = ByteBuffer.allocateDirect(100); try { + long elapsed = 0; for (;;) { System.out.println("Waiting to receive message"); + long start = System.nanoTime(); sel.select(5*1000); + long waited = (System.nanoTime() - start) / 1000_000; + elapsed += waited; + buf.clear(); SocketAddress sa = dc.receive(buf); // no datagram received if (sa == null) { if (expectedSender != null) { - throw new RuntimeException("Expected message not received"); + if (elapsed > 4800) { + throw new RuntimeException("Expected message not received"); + } else { + sel.selectedKeys().clear(); + continue; + } } System.out.println("No message received (correct)"); return; @@ -123,8 +133,8 @@ static void receiveDatagram(DatagramChannel dc, int receivedId = -1; try { receivedId = Integer.parseInt(s); - System.out.format("Received message from %s (id=0x%x)\n", - sender, receivedId); + System.out.format("Received message from %s (id=0x%x, length=%s)\n", + sender, receivedId, bytes.length); } catch (NumberFormatException x) { System.out.format("Received message from %s (msg=%s)\n", sender, s); } @@ -142,7 +152,6 @@ static void receiveDatagram(DatagramChannel dc, } sel.selectedKeys().clear(); - buf.rewind(); } } finally { sel.close(); @@ -160,6 +169,8 @@ static void test(ProtocolFamily family, throws IOException { System.out.format("\nTest DatagramChannel to %s socket\n", family.name()); + System.out.format("With interface=%s[%s]%n\twith bound addresses:%n\t%s%n", + nif.getDisplayName(), nif.getIndex(), nif.inetAddresses().toList()); try (DatagramChannel dc = (family == UNSPEC) ? DatagramChannel.open() : DatagramChannel.open(family)) { dc.setOption(StandardSocketOptions.SO_REUSEADDR, true) diff --git a/test/jdk/java/nio/channels/DatagramChannel/NotBound.java b/test/jdk/java/nio/channels/DatagramChannel/NotBound.java index 4cd9a03033642..bcd73591bf967 100644 --- a/test/jdk/java/nio/channels/DatagramChannel/NotBound.java +++ b/test/jdk/java/nio/channels/DatagramChannel/NotBound.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -24,19 +24,26 @@ /* @test * @bug 4512723 6621689 * @summary Test that connect/send/receive with unbound DatagramChannel causes - * the channel's socket to be bound to a local address + * the channel's socket to be bound to a local address. + * @run main/othervm NotBound */ import java.net.*; import java.nio.ByteBuffer; import java.nio.channels.DatagramChannel; import java.io.IOException; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; public class NotBound { + static final CountDownLatch received = new CountDownLatch(1); + static void checkBound(DatagramChannel dc) throws IOException { if (dc.getLocalAddress() == null) throw new RuntimeException("Not bound??"); + System.out.println("Bound to: " + dc.getLocalAddress()); } // starts a thread to send a datagram to the given channel once the channel @@ -51,19 +58,44 @@ public void run() { Thread.sleep(50); local = (InetSocketAddress)dc.getLocalAddress(); } while (local == null); + System.out.format("receiver bound to: %s%n", local); - // send message to channel to wakeup receiver - DatagramChannel sender = DatagramChannel.open(); - try { - ByteBuffer bb = ByteBuffer.wrap("hello".getBytes()); - InetAddress lh = InetAddress.getLocalHost(); - SocketAddress target = - new InetSocketAddress(lh, local.getPort()); - sender.send(bb, target); - } finally { - sender.close(); + boolean isAnyLocal = local.getAddress().isAnyLocalAddress(); + int maxAttempts = 5; + int localPort = 0; + List llh = isAnyLocal + ? List.of(InetAddress.getLocalHost(), InetAddress.getLoopbackAddress()) + : List.of(local.getAddress()); + SocketAddress target = null; + for (int i = 0 ; i < maxAttempts ; i++) { + InetAddress lh = llh.get(i % llh.size()); + target = new InetSocketAddress(lh, local.getPort()); + // send message to channel to wakeup receiver + try (DatagramChannel sender = DatagramChannel.open()) { + ByteBuffer bb = ByteBuffer.wrap("NotBound: hello".getBytes()); + sender.send(bb, target); + System.out.format("Woke up receiver: sent datagram to %s from %s%n", + target, sender.getLocalAddress()); + localPort = ((InetSocketAddress)sender.getLocalAddress()).getPort(); + } + if (received.await(250, TimeUnit.MILLISECONDS)) { + // The datagram has been received: no need to continue + // sending + break; + } + // if sender port and destination port were identical, which + // could happen on some systems, the receiver might not receive + // the datagram. So in that case we try again, bailing out if + // we had to retry too many times + if (localPort == local.getPort()) { + System.out.println("Local port and peer port are identical. Retrying..."); + } else { + System.out.println("Datagram not received after 250ms. Retrying..."); + } + } + if (localPort == local.getPort()) { + System.out.println("Couldn't find a port to send to " + target); } - } catch (Exception x) { x.printStackTrace(); } @@ -77,14 +109,12 @@ public static void main(String[] args) throws IOException { // connect dc = DatagramChannel.open(); try { - DatagramChannel peer = DatagramChannel.open() - .bind(new InetSocketAddress(0)); - int peerPort = ((InetSocketAddress)(peer.getLocalAddress())).getPort(); - try { + System.out.println("Check that connect() binds the socket"); + try (DatagramChannel peer = DatagramChannel.open()) { + peer.bind(new InetSocketAddress(0)); + int peerPort = ((InetSocketAddress)(peer.getLocalAddress())).getPort(); dc.connect(new InetSocketAddress(InetAddress.getLocalHost(), peerPort)); checkBound(dc); - } finally { - peer.close(); } } finally { dc.close(); @@ -93,7 +123,8 @@ public static void main(String[] args) throws IOException { // send dc = DatagramChannel.open(); try { - ByteBuffer bb = ByteBuffer.wrap("ignore this".getBytes()); + System.out.println("Check that send() binds the socket"); + ByteBuffer bb = ByteBuffer.wrap("NotBound: ignore this".getBytes()); SocketAddress target = new InetSocketAddress(InetAddress.getLocalHost(), 5000); dc.send(bb, target); @@ -105,9 +136,11 @@ public static void main(String[] args) throws IOException { // receive (blocking) dc = DatagramChannel.open(); try { + System.out.println("Check that blocking receive() binds the socket"); ByteBuffer bb = ByteBuffer.allocateDirect(128); wakeupWhenBound(dc); SocketAddress sender = dc.receive(bb); + received.countDown(); if (sender == null) throw new RuntimeException("Sender should not be null"); checkBound(dc); @@ -118,6 +151,7 @@ public static void main(String[] args) throws IOException { // receive (non-blocking) dc = DatagramChannel.open(); try { + System.out.println("Check that non-blocking receive() binds the socket"); dc.configureBlocking(false); ByteBuffer bb = ByteBuffer.allocateDirect(128); SocketAddress sender = dc.receive(bb); diff --git a/test/jdk/java/nio/channels/DatagramChannel/Promiscuous.java b/test/jdk/java/nio/channels/DatagramChannel/Promiscuous.java index 8db9c60c0b558..a8a5772b87b4f 100644 --- a/test/jdk/java/nio/channels/DatagramChannel/Promiscuous.java +++ b/test/jdk/java/nio/channels/DatagramChannel/Promiscuous.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -71,9 +71,11 @@ static int sendDatagram(NetworkInterface nif, dc.setOption(StandardSocketOptions.IP_MULTICAST_IF, nif); byte[] msg = Integer.toString(id).getBytes("UTF-8"); ByteBuffer buf = ByteBuffer.wrap(msg); - System.out.format("Send message -> group %s (id=0x%x)\n", - group.getHostAddress(), id); + System.out.format("Send message -> group [%s]:%d (id=0x%x) nif:%s[%s]%n", + group.getHostAddress(), port, id, nif.getDisplayName(), nif.getIndex()); + System.out.format("bound address before send: %s%n", dc.getLocalAddress()); dc.send(buf, new InetSocketAddress(group, port)); + System.out.format("bound address after send: %s%n", dc.getLocalAddress()); } return id; } @@ -97,15 +99,26 @@ static void receiveDatagram(DatagramChannel dc, ByteBuffer buf = ByteBuffer.allocateDirect(100); try { + long elapsed = 0; for (;;) { System.out.println("Waiting to receive message"); + long start = System.nanoTime(); sel.select(5*1000); + long waited = (System.nanoTime() - start) / 1000_000; + elapsed += waited; + buf.clear(); SocketAddress sa = dc.receive(buf); // no datagram received if (sa == null) { if (datagramExpected) { - throw new RuntimeException("Expected message not received"); + if (elapsed > 4800) { + throw new RuntimeException("Expected message not received"); + } else { + sel.selectedKeys().clear(); + // We haven't waited long enough, + continue; + } } System.out.println("No message received (correct)"); return; @@ -121,8 +134,8 @@ static void receiveDatagram(DatagramChannel dc, int receivedId = -1; try { receivedId = Integer.parseInt(s); - System.out.format("Received message from %s (id=0x%x)\n", - sender, receivedId); + System.out.format("Received message from %s (id=0x%x, length=%s)\n", + sender, receivedId, bytes.length); } catch (NumberFormatException x) { System.out.format("Received message from %s (msg=%s)\n", sender, s); } @@ -140,7 +153,6 @@ static void receiveDatagram(DatagramChannel dc, } sel.selectedKeys().clear(); - buf.rewind(); } } finally { sel.close(); @@ -155,13 +167,14 @@ static void test(ProtocolFamily family, { System.out.format("%nTest family=%s%n", family.name()); + System.out.format("With interface=%s[%s]%n\twith bound addresses:%n\t%s%n", + nif.getDisplayName(), nif.getIndex(), nif.inetAddresses().toList()); - DatagramChannel dc1 = (family == UNSPEC) ? - DatagramChannel.open() : DatagramChannel.open(family); - DatagramChannel dc2 = (family == UNSPEC) ? - DatagramChannel.open() : DatagramChannel.open(family); + try (DatagramChannel dc1 = (family == UNSPEC) ? + DatagramChannel.open() : DatagramChannel.open(family); + DatagramChannel dc2 = (family == UNSPEC) ? + DatagramChannel.open() : DatagramChannel.open(family)) { - try { dc1.setOption(StandardSocketOptions.SO_REUSEADDR, true); dc2.setOption(StandardSocketOptions.SO_REUSEADDR, true); @@ -184,12 +197,8 @@ static void test(ProtocolFamily family, id = sendDatagram(nif, group2, port); - receiveDatagram(dc1, "dc1", false, id); receiveDatagram(dc2, "dc2", true, id); - - } finally { - dc1.close(); - dc2.close(); + receiveDatagram(dc1, "dc1", false, id); } } diff --git a/test/jdk/java/nio/channels/DatagramChannel/ReceiveISA.java b/test/jdk/java/nio/channels/DatagramChannel/ReceiveISA.java index 69df204e91557..ef764c85d711e 100644 --- a/test/jdk/java/nio/channels/DatagramChannel/ReceiveISA.java +++ b/test/jdk/java/nio/channels/DatagramChannel/ReceiveISA.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2020, 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 @@ -27,10 +27,19 @@ * @summary Check that DatagramChannel.receive returns a new SocketAddress * when it receives a packet from the same source address but * different endpoint. + * @library /test/lib + * @build jdk.test.lib.NetworkConfiguration + * jdk.test.lib.Platform + * ReceiveISA + * @run main/othervm ReceiveISA + * */ import java.nio.*; import java.nio.channels.*; import java.net.*; + +import jdk.test.lib.Platform; + import static java.lang.System.out; public class ReceiveISA { @@ -44,10 +53,13 @@ public static void main(String args[]) throws Exception { DatagramChannel dc3 = DatagramChannel.open(); DatagramChannel dc4 = DatagramChannel.open()) { // client - dc3.socket().bind((SocketAddress) null); // bind server to any port + InetAddress lh = InetAddress.getLocalHost(); + InetSocketAddress dest = Platform.isOSX() + ? new InetSocketAddress(lh, 0) + : null; + dc3.socket().bind(dest); // bind server to any port // get server address - InetAddress lh = InetAddress.getLocalHost(); InetSocketAddress isa = new InetSocketAddress(lh, dc3.socket().getLocalPort()); ByteBuffer bb = ByteBuffer.allocateDirect(100); diff --git a/test/jdk/java/nio/channels/DatagramChannel/SelectWhenRefused.java b/test/jdk/java/nio/channels/DatagramChannel/SelectWhenRefused.java index d851e4f2b8148..58ccf9d0b80f9 100644 --- a/test/jdk/java/nio/channels/DatagramChannel/SelectWhenRefused.java +++ b/test/jdk/java/nio/channels/DatagramChannel/SelectWhenRefused.java @@ -39,8 +39,8 @@ import static org.junit.jupiter.api.Assertions.assertNotEquals; public class SelectWhenRefused { - static final int MAX_TRIES = 3; - static final String GREETINGS_MESSAGE = "Greetings from SelectWhenRefused!"; + static final int MAX_TRIES = 10; + static final String GREETINGS_MESSAGE = System.nanoTime() + ": Greetings from SelectWhenRefused!"; @Test public void test() throws IOException { @@ -49,9 +49,39 @@ public void test() throws IOException { // datagram sent to this address should be refused SocketAddress refuser = new InetSocketAddress(InetAddress.getLocalHost(), port); + System.err.println("Refuser is: " + refuser); - DatagramChannel dc = DatagramChannel.open().bind(new InetSocketAddress(0)); + DatagramChannel dc = null; + for (int i=0; i < MAX_TRIES; i++) { + dc = DatagramChannel.open(); + try { + dc.bind(new InetSocketAddress(0)); + } catch (Throwable t) { + dc.close(); + throw t; + } + + // check the port assigned to dc + if (((InetSocketAddress)dc.getLocalAddress()).getPort() != port) { + // We got a good port. Do not retry + break; + } + + // We bound to the same port that the refuser is using, This will not + // work. Retry binding if possible. + if (i < MAX_TRIES - 1) { + // we will retry... + System.err.format("Refuser port has been reused by dc: %s, retrying...%n", + dc.getLocalAddress()); + } else { + // that was the last attempt... Skip the test + System.err.format("Skipping test: refuser port has been reused by dc: %s%n", + dc.getLocalAddress()); + return; + } + } dc1.close(); + assert dc != null; Selector sel = Selector.open(); try { @@ -88,7 +118,7 @@ public void test() throws IOException { } } catch (BindException e) { // Do nothing, some other test has used this port - System.out.println("Skipping test: refuser port has been reused: " + e); + System.err.println("Skipping test: refuser port has been reused: " + e); } finally { sel.close(); dc.close(); @@ -119,7 +149,9 @@ static boolean testNoPUEBeforeConnection(DatagramChannel dc, // BindException will be thrown if another service is using // our expected refuser port, cannot run just exit. - DatagramChannel.open().bind(refuser).close(); + try (DatagramChannel dc2 = DatagramChannel.open()) { + dc2.bind(refuser); + } throw new RuntimeException("Unexpected wakeup"); } return true; // test passed @@ -151,7 +183,7 @@ static boolean testPUEOnConnect(DatagramChannel dc, byte[] bytes = new byte[buf.remaining()]; buf.get(bytes); String message = new String(bytes); - System.out.format("received %s at %s from %s%n", message, dc.getLocalAddress(), sa); + System.err.format("received %s at %s from %s%n", message, dc.getLocalAddress(), sa); // If any received data contains the message from sendDatagram then throw exception if (message.contains(GREETINGS_MESSAGE)) { @@ -166,10 +198,12 @@ static boolean testPUEOnConnect(DatagramChannel dc, // BindException will be thrown if another service is using // our expected refuser port, cannot run just exit. - DatagramChannel.open().bind(refuser).close(); + try (DatagramChannel dc2 = DatagramChannel.open()) { + dc2.bind(refuser); + } throw new RuntimeException("PortUnreachableException not raised"); } catch (PortUnreachableException pue) { - System.out.println("Got expected PortUnreachableException " + pue); + System.err.println("Got expected PortUnreachableException " + pue); } } return true; // test passed @@ -215,16 +249,16 @@ static void sendDatagram(DatagramChannel dc, SocketAddress remote) * */ static boolean checkUnexpectedWakeup(Set selectedKeys) { - System.out.format("Received %d keys%n", selectedKeys.size()); + System.err.format("Received %d keys%n", selectedKeys.size()); for (SelectionKey key : selectedKeys) { if (!key.isValid() || !key.isReadable()) { - System.out.println("Invalid or unreadable key: " + key); + System.err.println("Invalid or unreadable key: " + key); continue; } try { - System.out.println("Attempting to read datagram from key: " + key); + System.err.println("Attempting to read datagram from key: " + key); DatagramChannel datagramChannel = (DatagramChannel) key.channel(); ByteBuffer buf = ByteBuffer.allocate(100); SocketAddress sa = datagramChannel.receive(buf); @@ -234,7 +268,7 @@ static boolean checkUnexpectedWakeup(Set selectedKeys) { byte[] bytes = new byte[buf.remaining()]; buf.get(bytes); String message = new String(bytes); - System.out.format("received %s at %s from %s%n", message, datagramChannel.getLocalAddress(), sa); + System.err.format("received %s at %s from %s%n", message, datagramChannel.getLocalAddress(), sa); // If any received data contains the message from sendDatagram then return false if (message.contains(GREETINGS_MESSAGE)) { @@ -243,7 +277,7 @@ static boolean checkUnexpectedWakeup(Set selectedKeys) { } } catch (IOException io) { - System.out.println("Unable to read from datagram " + io); + System.err.println("Unable to read from datagram " + io); } } return true; diff --git a/test/jdk/java/nio/channels/DatagramChannel/SendReceiveMaxSize.java b/test/jdk/java/nio/channels/DatagramChannel/SendReceiveMaxSize.java index 31407ecb49359..8d74fd8a387a3 100644 --- a/test/jdk/java/nio/channels/DatagramChannel/SendReceiveMaxSize.java +++ b/test/jdk/java/nio/channels/DatagramChannel/SendReceiveMaxSize.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,6 +37,7 @@ import jdk.test.lib.NetworkConfiguration; import jdk.test.lib.Platform; import jdk.test.lib.net.IPSupport; +import org.testng.Assert; import org.testng.annotations.BeforeTest; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @@ -46,6 +47,7 @@ import java.net.Inet6Address; import java.net.InetAddress; import java.net.InetSocketAddress; +import java.net.SocketAddress; import java.nio.ByteBuffer; import java.nio.channels.DatagramChannel; import java.util.ArrayList; @@ -139,7 +141,9 @@ public void testSendReceiveMaxSize(DatagramChannelSupplier supplier, int capacit var addr = new InetSocketAddress(host, port); try (var sender = supplier.open()) { - sender.bind(null); + sender.bind(new InetSocketAddress(host, 0)); + System.out.format("testSendReceiveMaxSize: sender: %s -> receiver: %s%n", + sender.getLocalAddress(), receiver.getLocalAddress()); if (!Platform.isOSX()) { if (sender.getOption(SO_SNDBUF) < capacity) sender.setOption(SO_SNDBUF, capacity); @@ -150,7 +154,18 @@ public void testSendReceiveMaxSize(DatagramChannelSupplier supplier, int capacit var sendBuf = ByteBuffer.wrap(testData); sender.send(sendBuf, addr); var receiveBuf = ByteBuffer.allocate(capacity); - receiver.receive(receiveBuf); + SocketAddress src; + int count = 0; + do { + receiveBuf.clear(); + src = receiver.receive(receiveBuf); + if (sender.getLocalAddress().equals(src)) break; + System.out.println("step1: received unexpected datagram from: " + src); + System.out.println("\texpected: " + sender.getLocalAddress()); + if (++count > 10) { + throw new AssertionError("too many unexpected messages"); + } + } while (true); sendBuf.flip(); receiveBuf.flip(); @@ -167,7 +182,17 @@ public void testSendReceiveMaxSize(DatagramChannelSupplier supplier, int capacit sendBuf = ByteBuffer.wrap(testData); sender.send(sendBuf, addr); receiveBuf = ByteBuffer.allocate(capacity - 1); - receiver.receive(receiveBuf); + count = 0; + do { + receiveBuf.clear(); + src = receiver.receive(receiveBuf); + if (sender.getLocalAddress().equals(src)) break; + System.out.println("step1: received unexpected datagram from: " + src); + System.out.println("\texpected: " + sender.getLocalAddress()); + if (++count > 10) { + throw new AssertionError("too many unexpected messages"); + } + } while (true); sendBuf.flip(); receiveBuf.flip(); diff --git a/test/jdk/java/nio/channels/DatagramChannel/Sender.java b/test/jdk/java/nio/channels/DatagramChannel/Sender.java index 8ab4268e3a47a..fcecdf9d79aa9 100644 --- a/test/jdk/java/nio/channels/DatagramChannel/Sender.java +++ b/test/jdk/java/nio/channels/DatagramChannel/Sender.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -24,6 +24,9 @@ /* @test * @bug 4669040 8130394 * @summary Test DatagramChannel subsequent receives with no datagram ready + * @library /test/lib + * @build jdk.test.lib.Platform Sender + * @run main Sender * @author Mike McCloskey */ @@ -36,6 +39,8 @@ import java.nio.ByteOrder; import java.nio.channels.DatagramChannel; +import jdk.test.lib.Platform; + public class Sender { static PrintStream log = System.err; @@ -46,25 +51,26 @@ public static void main(String[] args) throws Exception { } static void test() throws Exception { - Server server = new Server(); - Client client = new Client(server.port()); + try (Server server = new Server()) { + Client client = new Client(server.port()); - Thread serverThread = new Thread(server); - serverThread.start(); + Thread serverThread = new Thread(server); + serverThread.start(); - Thread clientThread = new Thread(client); - clientThread.start(); + Thread clientThread = new Thread(client); + clientThread.start(); - serverThread.join(); - clientThread.join(); + serverThread.join(); + clientThread.join(); - server.throwException(); - client.throwException(); + server.throwException(); + client.throwException(); + } } public static class Client implements Runnable { final int port; - Exception e = null; + volatile Exception e = null; Client(int port) { this.port = port; @@ -76,14 +82,17 @@ void throwException() throws Exception { } public void run() { - try { - DatagramChannel dc = DatagramChannel.open(); + try (DatagramChannel dc = DatagramChannel.open()) { ByteBuffer bb = ByteBuffer.allocateDirect(12); bb.order(ByteOrder.BIG_ENDIAN); bb.putInt(1).putLong(1); bb.flip(); InetAddress address = InetAddress.getLocalHost(); InetSocketAddress isa = new InetSocketAddress(address, port); + if (Platform.isOSX()) { + // avoid binding on wildcard on macOS + dc.bind(new InetSocketAddress(address, 0)); + } dc.connect(isa); clientISA = dc.getLocalAddress(); dc.write(bb); @@ -93,12 +102,16 @@ public void run() { } } - public static class Server implements Runnable { + public static class Server implements Runnable, AutoCloseable { final DatagramChannel dc; - Exception e = null; + volatile Exception e = null; Server() throws IOException { - dc = DatagramChannel.open().bind(new InetSocketAddress(0)); + // avoid binding to wildcard address on macOS + InetSocketAddress lo = Platform.isOSX() + ? new InetSocketAddress(InetAddress.getLocalHost(), 0) + : new InetSocketAddress(0); + dc = DatagramChannel.open().bind(lo); } int port() { @@ -149,6 +162,11 @@ public void run() { e = ex; } } + + @Override + public void close() throws IOException { + dc.close(); + } } } diff --git a/test/jdk/jdk/jfr/event/compiler/TestCodeSweeper.java b/test/jdk/jdk/jfr/event/compiler/TestCodeSweeper.java index df95af5b9be0a..62fb137b1cf03 100644 --- a/test/jdk/jdk/jfr/event/compiler/TestCodeSweeper.java +++ b/test/jdk/jdk/jfr/event/compiler/TestCodeSweeper.java @@ -27,11 +27,9 @@ import java.lang.reflect.Method; import java.time.Instant; import java.util.ArrayList; -import java.util.Collections; import java.util.List; -import jdk.jfr.Event; -import jdk.jfr.consumer.RecordingStream; +import jdk.jfr.Recording; import jdk.jfr.consumer.RecordedEvent; import jdk.test.lib.Asserts; import jdk.test.lib.jfr.EventNames; @@ -41,7 +39,7 @@ import jdk.test.whitebox.code.CodeBlob; /** - * Test for events: jdk.CodeCacheFull jdk.CompilationFailure + * Test for events: vm/code_cache/full vm/compiler/failure * * We verify that we should get at least one of each of the events listed above. * @@ -60,15 +58,13 @@ */ public class TestCodeSweeper { - static class ProvocationEvent extends Event { - } private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); private static final int COMP_LEVEL_SIMPLE = 1; private static final int COMP_LEVEL_FULL_OPTIMIZATION = 4; private static final int SIZE = 1; private static final String METHOD_NAME = "verifyFullEvent"; - private static final String EVENT_CODE_CACHE_FULL = EventNames.CodeCacheFull; - private static final String EVENT_COMPILATION_FAILURE = EventNames.CompilationFailure; + private static final String pathFull = EventNames.CodeCacheFull; + private static final String pathFailure = EventNames.CompilationFailure; public static final long SEGMENT_SIZE = WhiteBox.getWhiteBox().getUintxVMFlag("CodeCacheSegmentSize"); public static final long MIN_BLOCK_LENGTH = WhiteBox.getWhiteBox().getUintxVMFlag("CodeCacheMinBlockLength"); public static final long MIN_ALLOCATION = SEGMENT_SIZE * MIN_BLOCK_LENGTH; @@ -81,41 +77,26 @@ public static void main(String[] args) throws Throwable { System.out.println("This test will warn that the code cache is full."); System.out.println("That is expected and is the purpose of the test."); System.out.println("************************************************"); - List events = Collections.synchronizedList(new ArrayList<>()); - try (RecordingStream rs = new RecordingStream()) { - rs.setReuse(false); - rs.enable(EVENT_CODE_CACHE_FULL); - rs.enable(EVENT_COMPILATION_FAILURE); - rs.onEvent(EVENT_CODE_CACHE_FULL, events::add); - rs.onEvent(EVENT_COMPILATION_FAILURE, events::add); - rs.onEvent(ProvocationEvent.class.getName(), e -> { - if (!events.isEmpty()) { - rs.close(); - return; - } - // Retry if CodeCacheFull or CompilationFailure events weren't provoked - try { - provokeEvents(); - } catch (Exception ex) { - ex.printStackTrace(); - rs.close(); - } - }); - rs.startAsync(); - provokeEvents(); - rs.awaitTermination(); - } + + Recording r = new Recording(); + r.enable(pathFull); + r.enable(pathFailure); + r.start(); + provokeEvents(); + r.stop(); int countEventFull = 0; int countEventFailure = 0; + + List events = Events.fromRecording(r); Events.hasEvents(events); - for (RecordedEvent event : new ArrayList<>(events)) { + for (RecordedEvent event : events) { switch (event.getEventType().getName()) { - case EVENT_CODE_CACHE_FULL: + case pathFull: countEventFull++; verifyFullEvent(event); break; - case EVENT_COMPILATION_FAILURE: + case pathFailure: countEventFailure++; verifyFailureEvent(event); break; @@ -134,8 +115,6 @@ private static boolean canAllocate(double size, long maxSize, MemoryPoolMXBean b } private static void provokeEvents() throws NoSuchMethodException, InterruptedException { - System.out.println("provokeEvents()"); - ProvocationEvent provocationEvent = new ProvocationEvent(); // Prepare for later, since we don't want to trigger any compilation // setting this up. Method method = TestCodeSweeper.class.getDeclaredMethod(METHOD_NAME, new Class[] { RecordedEvent.class }); @@ -180,7 +159,6 @@ private static void provokeEvents() throws NoSuchMethodException, InterruptedExc for (Long blob : blobs) { WHITE_BOX.freeCodeBlob(blob); } - provocationEvent.commit(); } private static void verifyFullEvent(RecordedEvent event) throws Throwable { diff --git a/test/langtools/jdk/javadoc/doclet/testPreview/TestPreview.java b/test/langtools/jdk/javadoc/doclet/testPreview/TestPreview.java index a59e68d25a063..369312d690a17 100644 --- a/test/langtools/jdk/javadoc/doclet/testPreview/TestPreview.java +++ b/test/langtools/jdk/javadoc/doclet/testPreview/TestPreview.java @@ -24,7 +24,7 @@ /* * @test * @bug 8250768 8261976 8277300 8282452 8287597 8325325 8325874 8297879 - * 8331947 + * 8331947 8281533 * @summary test generated docs for items declared using preview * @library ../../lib * @modules jdk.javadoc/jdk.javadoc.internal.tool @@ -156,7 +156,20 @@ public void testPreviewAPIJavadoc() {

  • java.base
  • preview
  • Core
  • - """); + """, + """ + """, + """ +
  • CoreRecord<\ + /a>PREVIEW<\ + /li> +
  • core record
  • """); // 8331947: Support preview features without JEP should not be included in Preview API page checkOutput("preview-list.html", false, "supportMethod"); diff --git a/test/langtools/jdk/javadoc/doclet/testPreview/api/preview/Core.java b/test/langtools/jdk/javadoc/doclet/testPreview/api/preview/Core.java index d2cf31c2e898b..1b23d20228523 100644 --- a/test/langtools/jdk/javadoc/doclet/testPreview/api/preview/Core.java +++ b/test/langtools/jdk/javadoc/doclet/testPreview/api/preview/Core.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,13 @@ import jdk.internal.javac.PreviewFeature; import jdk.internal.javac.PreviewFeature.Feature; +/** + * Preview feature. Links: {@link CoreRecord}, {@link CoreRecord core record}, + * {@linkplain CoreRecord}, {@linkplain CoreRecord core record}. + * + * @see CoreRecord + * @see CoreRecord core record + */ @PreviewFeature(feature=Feature.TEST) public class Core { } diff --git a/test/lib/jdk/test/lib/containers/docker/DockerTestUtils.java b/test/lib/jdk/test/lib/containers/docker/DockerTestUtils.java index c87796da47e7e..4a8915d463102 100644 --- a/test/lib/jdk/test/lib/containers/docker/DockerTestUtils.java +++ b/test/lib/jdk/test/lib/containers/docker/DockerTestUtils.java @@ -321,10 +321,11 @@ private static String limitLines(String buffer, int nrOfLines) { private static void generateDockerFile(Path dockerfile, String baseImage, String baseImageVersion) throws Exception { - String template = - "FROM %s:%s\n" + - "RUN apt-get install libubsan1\n" + - "COPY /jdk /jdk\n" + + String template = "FROM %s:%s\n"; + if (baseImage.contains("ubuntu") && DockerfileConfig.isUbsan()) { + template += "RUN apt-get update && apt-get install -y libubsan1\n"; + } + template = template + "COPY /jdk /jdk\n" + "ENV JAVA_HOME=/jdk\n" + "CMD [\"/bin/bash\"]\n"; String dockerFileStr = String.format(template, baseImage, baseImageVersion); diff --git a/test/lib/jdk/test/lib/containers/docker/DockerfileConfig.java b/test/lib/jdk/test/lib/containers/docker/DockerfileConfig.java index 9d73ad185f1f5..caa4a5a76ccf7 100644 --- a/test/lib/jdk/test/lib/containers/docker/DockerfileConfig.java +++ b/test/lib/jdk/test/lib/containers/docker/DockerfileConfig.java @@ -37,6 +37,11 @@ // Note: base image version should not be an empty string. Use "latest" to get the latest version. public class DockerfileConfig { + + public static boolean isUbsan() { + return Boolean.getBoolean("jdk.test.docker.image.isUbsan"); + } + public static String getBaseImageName() { String name = System.getProperty("jdk.test.docker.image.name"); if (name != null) {