From 968deb7658481da8c001e4ec94802dab8292cbf4 Mon Sep 17 00:00:00 2001 From: Antonios Printezis Date: Mon, 28 Jun 2010 14:13:18 -0400 Subject: [PATCH 01/56] 6962569: assembler_sparc.cpp:1969: assert(false) failed: error Array_overlap_test() fails when the address range crosses the MSB boundary. Thanks to Tom and Vladimir for their help on this one. Reviewed-by: kvn, never, iveresov --- hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp b/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp index 65404a44d66..99a7eebf4c4 100644 --- a/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp @@ -1007,9 +1007,9 @@ class StubGenerator: public StubCodeGenerator { __ brx(Assembler::lessEqualUnsigned, false, Assembler::pt, (*NOLp)); __ delayed()->cmp(to_from, byte_count); if (NOLp == NULL) - __ brx(Assembler::greaterEqual, false, Assembler::pt, no_overlap_target); + __ brx(Assembler::greaterEqualUnsigned, false, Assembler::pt, no_overlap_target); else - __ brx(Assembler::greaterEqual, false, Assembler::pt, (*NOLp)); + __ brx(Assembler::greaterEqualUnsigned, false, Assembler::pt, (*NOLp)); __ delayed()->nop(); } From dfc84e8c89a01342c3b1c706f974ed448617e68c Mon Sep 17 00:00:00 2001 From: Antonios Printezis Date: Mon, 28 Jun 2010 14:13:17 -0400 Subject: [PATCH 02/56] 6944166: G1: explicit GCs are not always handled correctly G1 was not handling explicit GCs correctly in many ways. It does now. See the CR for the list of improvements contained in this changeset. Reviewed-by: iveresov, ysr, johnc --- .../concurrentMarkSweep/vmCMSOperations.cpp | 5 + .../g1/concurrentMarkThread.cpp | 6 + .../gc_implementation/g1/g1CollectedHeap.cpp | 129 ++++++++++++++---- .../gc_implementation/g1/g1CollectedHeap.hpp | 49 +++++-- .../g1/g1CollectorPolicy.cpp | 52 ++++--- .../g1/g1CollectorPolicy.hpp | 16 ++- .../gc_implementation/g1/vm_operations_g1.cpp | 59 +++++++- .../gc_implementation/g1/vm_operations_g1.hpp | 35 +++-- .../vm/gc_implementation/includeDB_gc_g1 | 2 + .../shared/vmGCOperations.hpp | 4 +- hotspot/src/share/vm/gc_interface/gcCause.cpp | 3 + hotspot/src/share/vm/runtime/mutexLocker.cpp | 2 + 12 files changed, 291 insertions(+), 71 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/vmCMSOperations.cpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/vmCMSOperations.cpp index bcded9b04a8..bf5188ba74c 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/vmCMSOperations.cpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/vmCMSOperations.cpp @@ -234,6 +234,11 @@ void VM_GenCollectFullConcurrent::doit_epilogue() { GenCollectedHeap* gch = GenCollectedHeap::heap(); if (_gc_cause != GCCause::_gc_locker && gch->total_full_collections_completed() <= _full_gc_count_before) { + // maybe we should change the condition to test _gc_cause == + // GCCause::_java_lang_system_gc, instead of + // _gc_cause != GCCause::_gc_locker + assert(_gc_cause == GCCause::_java_lang_system_gc, + "the only way to get here if this was a System.gc()-induced GC"); assert(ExplicitGCInvokesConcurrent, "Error"); // Now, wait for witnessing concurrent gc cycle to complete, // but do so in native mode, because we want to lock the diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp index 8ecced2375b..88d9e01d0ab 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp @@ -266,6 +266,12 @@ void ConcurrentMarkThread::run() { _cm->clearNextBitmap(); _sts.leave(); } + + // Update the number of full collections that have been + // completed. This will also notify the FullGCCount_lock in case a + // Java thread is waiting for a full GC to happen (e.g., it + // called System.gc() with +ExplicitGCInvokesConcurrent). + g1->increment_full_collections_completed(true /* outer */); } assert(_should_terminate, "just checking"); diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp index b242e78ee7e..79622015207 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @@ -809,7 +809,8 @@ public: } }; -void G1CollectedHeap::do_collection(bool full, bool clear_all_soft_refs, +void G1CollectedHeap::do_collection(bool explicit_gc, + bool clear_all_soft_refs, size_t word_size) { if (GC_locker::check_active_before_gc()) { return; // GC is disabled (e.g. JNI GetXXXCritical operation) @@ -821,10 +822,6 @@ void G1CollectedHeap::do_collection(bool full, bool clear_all_soft_refs, Universe::print_heap_before_gc(); } - if (full && DisableExplicitGC) { - return; - } - assert(SafepointSynchronize::is_at_safepoint(), "should be at safepoint"); assert(Thread::current() == VMThread::vm_thread(), "should be in vm thread"); @@ -837,9 +834,11 @@ void G1CollectedHeap::do_collection(bool full, bool clear_all_soft_refs, IsGCActiveMark x; // Timing + bool system_gc = (gc_cause() == GCCause::_java_lang_system_gc); + assert(!system_gc || explicit_gc, "invariant"); gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps); TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty); - TraceTime t(full ? "Full GC (System.gc())" : "Full GC", + TraceTime t(system_gc ? "Full GC (System.gc())" : "Full GC", PrintGC, true, gclog_or_tty); TraceMemoryManagerStats tms(true /* fullGC */); @@ -944,7 +943,7 @@ void G1CollectedHeap::do_collection(bool full, bool clear_all_soft_refs, heap_region_iterate(&rs_clear); // Resize the heap if necessary. - resize_if_necessary_after_full_collection(full ? 0 : word_size); + resize_if_necessary_after_full_collection(explicit_gc ? 0 : word_size); if (_cg1r->use_cache()) { _cg1r->clear_and_record_card_counts(); @@ -1009,13 +1008,18 @@ void G1CollectedHeap::do_collection(bool full, bool clear_all_soft_refs, "young list should be empty at this point"); } + // Update the number of full collections that have been completed. + increment_full_collections_completed(false /* outer */); + if (PrintHeapAtGC) { Universe::print_heap_after_gc(); } } void G1CollectedHeap::do_full_collection(bool clear_all_soft_refs) { - do_collection(true, clear_all_soft_refs, 0); + do_collection(true, /* explicit_gc */ + clear_all_soft_refs, + 0 /* word_size */); } // This code is mostly copied from TenuredGeneration. @@ -1331,6 +1335,7 @@ G1CollectedHeap::G1CollectedHeap(G1CollectorPolicy* policy_) : _young_list(new YoungList(this)), _gc_time_stamp(0), _surviving_young_words(NULL), + _full_collections_completed(0), _in_cset_fast_test(NULL), _in_cset_fast_test_base(NULL), _dirty_cards_region_list(NULL) { @@ -1689,6 +1694,51 @@ size_t G1CollectedHeap::unsafe_max_alloc() { return car->free(); } +bool G1CollectedHeap::should_do_concurrent_full_gc(GCCause::Cause cause) { + return + ((cause == GCCause::_gc_locker && GCLockerInvokesConcurrent) || + (cause == GCCause::_java_lang_system_gc && ExplicitGCInvokesConcurrent)); +} + +void G1CollectedHeap::increment_full_collections_completed(bool outer) { + MonitorLockerEx x(FullGCCount_lock, Mutex::_no_safepoint_check_flag); + + // We have already incremented _total_full_collections at the start + // of the GC, so total_full_collections() represents how many full + // collections have been started. + unsigned int full_collections_started = total_full_collections(); + + // Given that this method is called at the end of a Full GC or of a + // concurrent cycle, and those can be nested (i.e., a Full GC can + // interrupt a concurrent cycle), the number of full collections + // completed should be either one (in the case where there was no + // nesting) or two (when a Full GC interrupted a concurrent cycle) + // behind the number of full collections started. + + // This is the case for the inner caller, i.e. a Full GC. + assert(outer || + (full_collections_started == _full_collections_completed + 1) || + (full_collections_started == _full_collections_completed + 2), + err_msg("for inner caller: full_collections_started = %u " + "is inconsistent with _full_collections_completed = %u", + full_collections_started, _full_collections_completed)); + + // This is the case for the outer caller, i.e. the concurrent cycle. + assert(!outer || + (full_collections_started == _full_collections_completed + 1), + err_msg("for outer caller: full_collections_started = %u " + "is inconsistent with _full_collections_completed = %u", + full_collections_started, _full_collections_completed)); + + _full_collections_completed += 1; + + // This notify_all() will ensure that a thread that called + // System.gc() with (with ExplicitGCInvokesConcurrent set or not) + // and it's waiting for a full GC to finish will be woken up. It is + // waiting in VM_G1IncCollectionPause::doit_epilogue(). + FullGCCount_lock->notify_all(); +} + void G1CollectedHeap::collect_as_vm_thread(GCCause::Cause cause) { assert(Thread::current()->is_VM_thread(), "Precondition#1"); assert(Heap_lock->is_locked(), "Precondition#2"); @@ -1709,25 +1759,41 @@ void G1CollectedHeap::collect(GCCause::Cause cause) { // The caller doesn't have the Heap_lock assert(!Heap_lock->owned_by_self(), "this thread should not own the Heap_lock"); - int gc_count_before; + unsigned int gc_count_before; + unsigned int full_gc_count_before; { MutexLocker ml(Heap_lock); // Read the GC count while holding the Heap_lock gc_count_before = SharedHeap::heap()->total_collections(); + full_gc_count_before = SharedHeap::heap()->total_full_collections(); // Don't want to do a GC until cleanup is completed. wait_for_cleanup_complete(); - } // We give up heap lock; VMThread::execute gets it back below - switch (cause) { - case GCCause::_scavenge_alot: { - // Do an incremental pause, which might sometimes be abandoned. - VM_G1IncCollectionPause op(gc_count_before, cause); + + // We give up heap lock; VMThread::execute gets it back below + } + + if (should_do_concurrent_full_gc(cause)) { + // Schedule an initial-mark evacuation pause that will start a + // concurrent cycle. + VM_G1IncCollectionPause op(gc_count_before, + true, /* should_initiate_conc_mark */ + g1_policy()->max_pause_time_ms(), + cause); + VMThread::execute(&op); + } else { + if (cause == GCCause::_gc_locker + DEBUG_ONLY(|| cause == GCCause::_scavenge_alot)) { + + // Schedule a standard evacuation pause. + VM_G1IncCollectionPause op(gc_count_before, + false, /* should_initiate_conc_mark */ + g1_policy()->max_pause_time_ms(), + cause); VMThread::execute(&op); - break; - } - default: { - // In all other cases, we currently do a full gc. - VM_G1CollectFull op(gc_count_before, cause); + } else { + // Schedule a Full GC. + VM_G1CollectFull op(gc_count_before, full_gc_count_before, cause); VMThread::execute(&op); } } @@ -1989,6 +2055,11 @@ void G1CollectedHeap::collection_set_iterate(HeapRegionClosure* cl) { void G1CollectedHeap::collection_set_iterate_from(HeapRegion* r, HeapRegionClosure *cl) { + if (r == NULL) { + // The CSet is empty so there's nothing to do. + return; + } + assert(r->in_collection_set(), "Start region must be a member of the collection set."); HeapRegion* cur = r; @@ -2481,11 +2552,13 @@ void G1CollectedHeap::gc_epilogue(bool full /* Ignored */) { } void G1CollectedHeap::do_collection_pause() { + assert(Heap_lock->owned_by_self(), "we assume we'reholding the Heap_lock"); + // Read the GC count while holding the Heap_lock // we need to do this _before_ wait_for_cleanup_complete(), to // ensure that we do not give up the heap lock and potentially // pick up the wrong count - int gc_count_before = SharedHeap::heap()->total_collections(); + unsigned int gc_count_before = SharedHeap::heap()->total_collections(); // Don't want to do a GC pause while cleanup is being completed! wait_for_cleanup_complete(); @@ -2493,7 +2566,10 @@ void G1CollectedHeap::do_collection_pause() { g1_policy()->record_stop_world_start(); { MutexUnlocker mu(Heap_lock); // give up heap lock, execute gets it back - VM_G1IncCollectionPause op(gc_count_before); + VM_G1IncCollectionPause op(gc_count_before, + false, /* should_initiate_conc_mark */ + g1_policy()->max_pause_time_ms(), + GCCause::_g1_inc_collection_pause); VMThread::execute(&op); } } @@ -2612,7 +2688,7 @@ struct PrepareForRSScanningClosure : public HeapRegionClosure { }; void -G1CollectedHeap::do_collection_pause_at_safepoint() { +G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) { if (GC_locker::check_active_before_gc()) { return; // GC is disabled (e.g. JNI GetXXXCritical operation) } @@ -2637,8 +2713,12 @@ G1CollectedHeap::do_collection_pause_at_safepoint() { else strcat(verbose_str, "(partial)"); } - if (g1_policy()->during_initial_mark_pause()) + if (g1_policy()->during_initial_mark_pause()) { strcat(verbose_str, " (initial-mark)"); + // We are about to start a marking cycle, so we increment the + // full collection counter. + increment_total_full_collections(); + } // if PrintGCDetails is on, we'll print long statistics information // in the collector policy code, so let's not print this as the output @@ -2661,7 +2741,6 @@ G1CollectedHeap::do_collection_pause_at_safepoint() { "young list should be well formed"); } - bool abandoned = false; { // Call to jvmpi::post_class_unload_events must occur outside of active GC IsGCActiveMark x; @@ -2743,7 +2822,7 @@ G1CollectedHeap::do_collection_pause_at_safepoint() { // Now choose the CS. We may abandon a pause if we find no // region that will fit in the MMU pause. - bool abandoned = g1_policy()->choose_collection_set(); + bool abandoned = g1_policy()->choose_collection_set(target_pause_time_ms); // Nothing to do if we were unable to choose a collection set. if (!abandoned) { diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp index 38b44e72c75..74606c18bdf 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp @@ -277,6 +277,18 @@ private: void update_surviving_young_words(size_t* surv_young_words); void cleanup_surviving_young_words(); + // It decides whether an explicit GC should start a concurrent cycle + // instead of doing a STW GC. Currently, a concurrent cycle is + // explicitly started if: + // (a) cause == _gc_locker and +GCLockerInvokesConcurrent, or + // (b) cause == _java_lang_system_gc and +ExplicitGCInvokesConcurrent. + bool should_do_concurrent_full_gc(GCCause::Cause cause); + + // Keeps track of how many "full collections" (i.e., Full GCs or + // concurrent cycles) we have completed. The number of them we have + // started is maintained in _total_full_collections in CollectedHeap. + volatile unsigned int _full_collections_completed; + protected: // Returns "true" iff none of the gc alloc regions have any allocations @@ -356,13 +368,14 @@ protected: // GC pause. void retire_alloc_region(HeapRegion* alloc_region, bool par); - // Helper function for two callbacks below. - // "full", if true, indicates that the GC is for a System.gc() request, - // and should collect the entire heap. If "clear_all_soft_refs" is true, - // all soft references are cleared during the GC. If "full" is false, - // "word_size" describes the allocation that the GC should - // attempt (at least) to satisfy. - void do_collection(bool full, bool clear_all_soft_refs, + // - if explicit_gc is true, the GC is for a System.gc() or a heap + // inspection request and should collect the entire heap + // - if clear_all_soft_refs is true, all soft references are cleared + // during the GC + // - if explicit_gc is false, word_size describes the allocation that + // the GC should attempt (at least) to satisfy + void do_collection(bool explicit_gc, + bool clear_all_soft_refs, size_t word_size); // Callback from VM_G1CollectFull operation. @@ -431,6 +444,26 @@ public: _in_cset_fast_test_length * sizeof(bool)); } + // This is called at the end of either a concurrent cycle or a Full + // GC to update the number of full collections completed. Those two + // can happen in a nested fashion, i.e., we start a concurrent + // cycle, a Full GC happens half-way through it which ends first, + // and then the cycle notices that a Full GC happened and ends + // too. The outer parameter is a boolean to help us do a bit tighter + // consistency checking in the method. If outer is false, the caller + // is the inner caller in the nesting (i.e., the Full GC). If outer + // is true, the caller is the outer caller in this nesting (i.e., + // the concurrent cycle). Further nesting is not currently + // supported. The end of the this call also notifies the + // FullGCCount_lock in case a Java thread is waiting for a full GC + // to happen (e.g., it called System.gc() with + // +ExplicitGCInvokesConcurrent). + void increment_full_collections_completed(bool outer); + + unsigned int full_collections_completed() { + return _full_collections_completed; + } + protected: // Shrink the garbage-first heap by at most the given size (in bytes!). @@ -444,7 +477,7 @@ protected: // The guts of the incremental collection pause, executed by the vm // thread. - virtual void do_collection_pause_at_safepoint(); + virtual void do_collection_pause_at_safepoint(double target_pause_time_ms); // Actually do the work of evacuating the collection set. virtual void evacuate_collection_set(); diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp index 1eeba34217c..0cb73eb0c6b 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp @@ -154,7 +154,6 @@ G1CollectorPolicy::G1CollectorPolicy() : _known_garbage_bytes(0), _young_gc_eff_seq(new TruncatedSeq(TruncatedSeqLength)), - _target_pause_time_ms(-1.0), _recent_prev_end_times_for_all_gcs_sec(new TruncatedSeq(NumPrevPausesForHeuristics)), @@ -1635,8 +1634,6 @@ void G1CollectorPolicy::record_collection_pause_end(bool abandoned) { double update_rs_time_goal_ms = _mmu_tracker->max_gc_time() * MILLIUNITS * G1RSetUpdatingPauseTimePercent / 100.0; adjust_concurrent_refinement(update_rs_time, update_rs_processed_buffers, update_rs_time_goal_ms); // - - _target_pause_time_ms = -1.0; } // @@ -2366,7 +2363,6 @@ G1CollectorPolicy_BestRegionsFirst::should_do_collection_pause(size_t if (reached_target_length) { assert( young_list_length > 0 && _g1->young_list()->length() > 0, "invariant" ); - _target_pause_time_ms = max_pause_time_ms; return true; } } else { @@ -2398,6 +2394,17 @@ bool G1CollectorPolicy_BestRegionsFirst::assertMarkedBytesDataOK() { } #endif +bool +G1CollectorPolicy::force_initial_mark_if_outside_cycle() { + bool during_cycle = _g1->concurrent_mark()->cmThread()->during_cycle(); + if (!during_cycle) { + set_initiate_conc_mark_if_possible(); + return true; + } else { + return false; + } +} + void G1CollectorPolicy::decide_on_conc_mark_initiation() { // We are about to decide on whether this pause will be an @@ -2864,7 +2871,8 @@ void G1CollectorPolicy::print_collection_set(HeapRegion* list_head, outputStream #endif // !PRODUCT bool -G1CollectorPolicy_BestRegionsFirst::choose_collection_set() { +G1CollectorPolicy_BestRegionsFirst::choose_collection_set( + double target_pause_time_ms) { // Set this here - in case we're not doing young collections. double non_young_start_time_sec = os::elapsedTime(); @@ -2877,26 +2885,19 @@ G1CollectorPolicy_BestRegionsFirst::choose_collection_set() { start_recording_regions(); - guarantee(_target_pause_time_ms > -1.0 - NOT_PRODUCT(|| Universe::heap()->gc_cause() == GCCause::_scavenge_alot), - "_target_pause_time_ms should have been set!"); -#ifndef PRODUCT - if (_target_pause_time_ms <= -1.0) { - assert(ScavengeALot && Universe::heap()->gc_cause() == GCCause::_scavenge_alot, "Error"); - _target_pause_time_ms = _mmu_tracker->max_gc_time() * 1000.0; - } -#endif - assert(_collection_set == NULL, "Precondition"); + guarantee(target_pause_time_ms > 0.0, + err_msg("target_pause_time_ms = %1.6lf should be positive", + target_pause_time_ms)); + guarantee(_collection_set == NULL, "Precondition"); double base_time_ms = predict_base_elapsed_time_ms(_pending_cards); double predicted_pause_time_ms = base_time_ms; - double target_time_ms = _target_pause_time_ms; - double time_remaining_ms = target_time_ms - base_time_ms; + double time_remaining_ms = target_pause_time_ms - base_time_ms; // the 10% and 50% values are arbitrary... - if (time_remaining_ms < 0.10*target_time_ms) { - time_remaining_ms = 0.50 * target_time_ms; + if (time_remaining_ms < 0.10 * target_pause_time_ms) { + time_remaining_ms = 0.50 * target_pause_time_ms; _within_target = false; } else { _within_target = true; @@ -3059,7 +3060,18 @@ choose_collection_set_end: _recorded_non_young_cset_choice_time_ms = (non_young_end_time_sec - non_young_start_time_sec) * 1000.0; - return abandon_collection; + // Here we are supposed to return whether the pause should be + // abandoned or not (i.e., whether the collection set is empty or + // not). However, this introduces a subtle issue when a pause is + // initiated explicitly with System.gc() and + // +ExplicitGCInvokesConcurrent (see Comment #2 in CR 6944166), it's + // supposed to start a marking cycle, and it's abandoned. So, by + // returning false here we are telling the caller never to consider + // a pause to be abandoned. We'll actually remove all the code + // associated with abandoned pauses as part of CR 6963209, but we are + // just disabling them this way for the moment to avoid increasing + // further the amount of changes for CR 6944166. + return false; } void G1CollectorPolicy_BestRegionsFirst::record_full_collection_end() { diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp index b6f885d4534..61dbee6c09e 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp @@ -199,8 +199,6 @@ protected: size_t _young_cset_length; bool _last_young_gc_full; - double _target_pause_time_ms; - unsigned _full_young_pause_num; unsigned _partial_young_pause_num; @@ -526,6 +524,10 @@ public: return _mmu_tracker; } + double max_pause_time_ms() { + return _mmu_tracker->max_gc_time() * 1000.0; + } + double predict_init_time_ms() { return get_new_prediction(_concurrent_mark_init_times_ms); } @@ -1008,7 +1010,7 @@ public: // Choose a new collection set. Marks the chosen regions as being // "in_collection_set", and links them together. The head and number of // the collection set are available via access methods. - virtual bool choose_collection_set() = 0; + virtual bool choose_collection_set(double target_pause_time_ms) = 0; // The head of the list (via "next_in_collection_set()") representing the // current collection set. @@ -1077,6 +1079,12 @@ public: void set_during_initial_mark_pause() { _during_initial_mark_pause = true; } void clear_during_initial_mark_pause(){ _during_initial_mark_pause = false; } + // This sets the initiate_conc_mark_if_possible() flag to start a + // new cycle, as long as we are not already in one. It's best if it + // is called during a safepoint when the test whether a cycle is in + // progress or not is stable. + bool force_initial_mark_if_outside_cycle(); + // This is called at the very beginning of an evacuation pause (it // has to be the first thing that the pause does). If // initiate_conc_mark_if_possible() is true, and the concurrent @@ -1259,7 +1267,7 @@ class G1CollectorPolicy_BestRegionsFirst: public G1CollectorPolicy { // If the estimated is less then desirable, resize if possible. void expand_if_possible(size_t numRegions); - virtual bool choose_collection_set(); + virtual bool choose_collection_set(double target_pause_time_ms); virtual void record_collection_pause_start(double start_time_sec, size_t start_used); virtual void record_concurrent_mark_cleanup_end(size_t freed_bytes, diff --git a/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp b/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp index 02370cadc18..575e6781786 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp @@ -42,8 +42,65 @@ void VM_G1CollectFull::doit() { void VM_G1IncCollectionPause::doit() { JvmtiGCForAllocationMarker jgcm; G1CollectedHeap* g1h = G1CollectedHeap::heap(); + assert(!_should_initiate_conc_mark || + ((_gc_cause == GCCause::_gc_locker && GCLockerInvokesConcurrent) || + (_gc_cause == GCCause::_java_lang_system_gc && ExplicitGCInvokesConcurrent)), + "only a GC locker or a System.gc() induced GC should start a cycle"); + GCCauseSetter x(g1h, _gc_cause); - g1h->do_collection_pause_at_safepoint(); + if (_should_initiate_conc_mark) { + // It's safer to read full_collections_completed() here, given + // that noone else will be updating it concurrently. Since we'll + // only need it if we're initiating a marking cycle, no point in + // setting it earlier. + _full_collections_completed_before = g1h->full_collections_completed(); + + // At this point we are supposed to start a concurrent cycle. We + // will do so if one is not already in progress. + bool res = g1h->g1_policy()->force_initial_mark_if_outside_cycle(); + } + g1h->do_collection_pause_at_safepoint(_target_pause_time_ms); +} + +void VM_G1IncCollectionPause::doit_epilogue() { + VM_GC_Operation::doit_epilogue(); + + // If the pause was initiated by a System.gc() and + // +ExplicitGCInvokesConcurrent, we have to wait here for the cycle + // that just started (or maybe one that was already in progress) to + // finish. + if (_gc_cause == GCCause::_java_lang_system_gc && + _should_initiate_conc_mark) { + assert(ExplicitGCInvokesConcurrent, + "the only way to be here is if ExplicitGCInvokesConcurrent is set"); + + G1CollectedHeap* g1h = G1CollectedHeap::heap(); + + // In the doit() method we saved g1h->full_collections_completed() + // in the _full_collections_completed_before field. We have to + // wait until we observe that g1h->full_collections_completed() + // has increased by at least one. This can happen if a) we started + // a cycle and it completes, b) a cycle already in progress + // completes, or c) a Full GC happens. + + // If the condition has already been reached, there's no point in + // actually taking the lock and doing the wait. + if (g1h->full_collections_completed() <= + _full_collections_completed_before) { + // The following is largely copied from CMS + + Thread* thr = Thread::current(); + assert(thr->is_Java_thread(), "invariant"); + JavaThread* jt = (JavaThread*)thr; + ThreadToNativeFromVM native(jt); + + MutexLockerEx x(FullGCCount_lock, Mutex::_no_safepoint_check_flag); + while (g1h->full_collections_completed() <= + _full_collections_completed_before) { + FullGCCount_lock->wait(Mutex::_no_safepoint_check_flag); + } + } + } } void VM_CGC_Operation::doit() { diff --git a/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.hpp b/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.hpp index 3368c300eaf..d05beac9ea1 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.hpp @@ -31,13 +31,12 @@ // - VM_G1PopRegionCollectionPause class VM_G1CollectFull: public VM_GC_Operation { - private: public: - VM_G1CollectFull(int gc_count_before, - GCCause::Cause gc_cause) - : VM_GC_Operation(gc_count_before) - { - _gc_cause = gc_cause; + VM_G1CollectFull(unsigned int gc_count_before, + unsigned int full_gc_count_before, + GCCause::Cause cause) + : VM_GC_Operation(gc_count_before, full_gc_count_before) { + _gc_cause = cause; } ~VM_G1CollectFull() {} virtual VMOp_Type type() const { return VMOp_G1CollectFull; } @@ -67,12 +66,28 @@ class VM_G1CollectForAllocation: public VM_GC_Operation { }; class VM_G1IncCollectionPause: public VM_GC_Operation { - public: - VM_G1IncCollectionPause(int gc_count_before, - GCCause::Cause gc_cause = GCCause::_g1_inc_collection_pause) : - VM_GC_Operation(gc_count_before) { _gc_cause = gc_cause; } +private: + bool _should_initiate_conc_mark; + double _target_pause_time_ms; + unsigned int _full_collections_completed_before; +public: + VM_G1IncCollectionPause(unsigned int gc_count_before, + bool should_initiate_conc_mark, + double target_pause_time_ms, + GCCause::Cause cause) + : VM_GC_Operation(gc_count_before), + _full_collections_completed_before(0), + _should_initiate_conc_mark(should_initiate_conc_mark), + _target_pause_time_ms(target_pause_time_ms) { + guarantee(target_pause_time_ms > 0.0, + err_msg("target_pause_time_ms = %1.6lf should be positive", + target_pause_time_ms)); + + _gc_cause = cause; + } virtual VMOp_Type type() const { return VMOp_G1IncCollectionPause; } virtual void doit(); + virtual void doit_epilogue(); virtual const char* name() const { return "garbage-first incremental collection pause"; } diff --git a/hotspot/src/share/vm/gc_implementation/includeDB_gc_g1 b/hotspot/src/share/vm/gc_implementation/includeDB_gc_g1 index dd271e1d1d8..13e3464ed8f 100644 --- a/hotspot/src/share/vm/gc_implementation/includeDB_gc_g1 +++ b/hotspot/src/share/vm/gc_implementation/includeDB_gc_g1 @@ -367,4 +367,6 @@ vm_operations_g1.hpp vmGCOperations.hpp vm_operations_g1.cpp vm_operations_g1.hpp vm_operations_g1.cpp g1CollectedHeap.inline.hpp +vm_operations_g1.cpp g1CollectorPolicy.hpp +vm_operations_g1.cpp interfaceSupport.hpp vm_operations_g1.cpp isGCActiveMark.hpp diff --git a/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.hpp b/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.hpp index d70d78ab92f..b3a202902a5 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.hpp +++ b/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.hpp @@ -86,9 +86,7 @@ class VM_GC_Operation: public VM_Operation { _gc_locked = false; - if (full) { - _full_gc_count_before = full_gc_count_before; - } + _full_gc_count_before = full_gc_count_before; // In ParallelScavengeHeap::mem_allocate() collections can be // executed within a loop and _all_soft_refs_clear can be set // true after they have been cleared by a collection and another diff --git a/hotspot/src/share/vm/gc_interface/gcCause.cpp b/hotspot/src/share/vm/gc_interface/gcCause.cpp index 19822c92777..e96f55a86ee 100644 --- a/hotspot/src/share/vm/gc_interface/gcCause.cpp +++ b/hotspot/src/share/vm/gc_interface/gcCause.cpp @@ -78,6 +78,9 @@ const char* GCCause::to_string(GCCause::Cause cause) { case _old_generation_too_full_to_scavenge: return "Old Generation Too Full To Scavenge"; + case _g1_inc_collection_pause: + return "G1 Evacuation Pause"; + case _last_ditch_collection: return "Last ditch collection"; diff --git a/hotspot/src/share/vm/runtime/mutexLocker.cpp b/hotspot/src/share/vm/runtime/mutexLocker.cpp index 71cbc771856..93f1e2feea0 100644 --- a/hotspot/src/share/vm/runtime/mutexLocker.cpp +++ b/hotspot/src/share/vm/runtime/mutexLocker.cpp @@ -159,6 +159,8 @@ void mutex_init() { def(STS_init_lock , Mutex, leaf, true ); if (UseConcMarkSweepGC) { def(iCMS_lock , Monitor, special, true ); // CMS incremental mode start/stop notification + } + if (UseConcMarkSweepGC || UseG1GC) { def(FullGCCount_lock , Monitor, leaf, true ); // in support of ExplicitGCInvokesConcurrent } if (UseG1GC) { From bd18ff374c4db44c2739605b63566df61f55da1a Mon Sep 17 00:00:00 2001 From: Dmitry Samersoff Date: Tue, 13 Jul 2010 15:32:36 +0400 Subject: [PATCH 03/56] 6964714: NetworkInterface getInetAddresses enumerates IPv6 addresses if java.net.preferIPvStack property set User can disable ipv6 explicitly, have to check it Reviewed-by: chegar, alanb --- .../native/java/net/NetworkInterface.c | 30 +++++++---- .../java/net/NetworkInterface/IPv4Only.java | 51 +++++++++++++++++++ 2 files changed, 70 insertions(+), 11 deletions(-) create mode 100644 jdk/test/java/net/NetworkInterface/IPv4Only.java diff --git a/jdk/src/solaris/native/java/net/NetworkInterface.c b/jdk/src/solaris/native/java/net/NetworkInterface.c index 58675462b96..eb4b2929dae 100644 --- a/jdk/src/solaris/native/java/net/NetworkInterface.c +++ b/jdk/src/solaris/native/java/net/NetworkInterface.c @@ -753,19 +753,27 @@ static netif *enumInterfaces(JNIEnv *env) { * If IPv6 is available then enumerate IPv6 addresses. */ #ifdef AF_INET6 - sock = openSocket(env, AF_INET6); - if (sock < 0 && (*env)->ExceptionOccurred(env)) { - freeif(ifs); - return NULL; - } - ifs = enumIPv6Interfaces(env, sock, ifs); - close(sock); + /* User can disable ipv6 expicitly by -Djava.net.preferIPv4Stack=true, + * so we have to call ipv6_available() + */ + if (ipv6_available()) { - if ((*env)->ExceptionOccurred(env)) { - freeif(ifs); - return NULL; - } + sock = openSocket(env, AF_INET6); + if (sock < 0 && (*env)->ExceptionOccurred(env)) { + freeif(ifs); + return NULL; + } + + ifs = enumIPv6Interfaces(env, sock, ifs); + close(sock); + + if ((*env)->ExceptionOccurred(env)) { + freeif(ifs); + return NULL; + } + + } #endif return ifs; diff --git a/jdk/test/java/net/NetworkInterface/IPv4Only.java b/jdk/test/java/net/NetworkInterface/IPv4Only.java new file mode 100644 index 00000000000..dcbfac1ac2e --- /dev/null +++ b/jdk/test/java/net/NetworkInterface/IPv4Only.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * 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 6964714 + * @run main/othervm NetworkInterfaceV6List + * @summary Test the networkinterface listing with java.net.preferIPv4Stack=true. + */ + + +import java.net.*; +import java.util.*; + + +public class IPv4Only { + public static void main(String[] args) throws Exception { + System.setProperty("java.net.preferIPv4Stack","true"); + + Enumeration nifs = NetworkInterface.getNetworkInterfaces(); + while (nifs.hasMoreElements()) { + NetworkInterface nif = nifs.nextElement(); + Enumeration addrs = nif.getInetAddresses(); + while (addrs.hasMoreElements()) { + InetAddress hostAddr = addrs.nextElement(); + if ( hostAddr instanceof Inet6Address ){ + throw new RuntimeException( "NetworkInterfaceV6List failed - found v6 address " + hostAddr.getHostAddress() ); + } + } + } + } +} From c20e1ffd6c0accb737fb45c36daf079bf4499685 Mon Sep 17 00:00:00 2001 From: Weijun Wang Date: Tue, 13 Jul 2010 20:27:01 +0800 Subject: [PATCH 04/56] 6670889: Keystore created under Hindi Locale causing ArrayIndexOutOfBoundsException Reviewed-by: chegar --- .../sun/security/util/DerOutputStream.java | 7 ++-- .../util/DerOutputStream/LocaleInTime.java | 42 +++++++++++++++++++ 2 files changed, 45 insertions(+), 4 deletions(-) create mode 100644 jdk/test/sun/security/util/DerOutputStream/LocaleInTime.java diff --git a/jdk/src/share/classes/sun/security/util/DerOutputStream.java b/jdk/src/share/classes/sun/security/util/DerOutputStream.java index f5400c634ec..c517df8a43e 100644 --- a/jdk/src/share/classes/sun/security/util/DerOutputStream.java +++ b/jdk/src/share/classes/sun/security/util/DerOutputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved. * 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,17 +25,16 @@ package sun.security.util; -import java.io.FilterOutputStream; import java.io.ByteArrayOutputStream; import java.io.OutputStream; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.TimeZone; -import java.util.Vector; import java.util.Comparator; import java.util.Arrays; import java.math.BigInteger; +import java.util.Locale; /** @@ -501,7 +500,7 @@ extends ByteArrayOutputStream implements DerEncoder { pattern = "yyyyMMddHHmmss'Z'"; } - SimpleDateFormat sdf = new SimpleDateFormat(pattern); + SimpleDateFormat sdf = new SimpleDateFormat(pattern, Locale.US); sdf.setTimeZone(tz); byte[] time = (sdf.format(d)).getBytes("ISO-8859-1"); diff --git a/jdk/test/sun/security/util/DerOutputStream/LocaleInTime.java b/jdk/test/sun/security/util/DerOutputStream/LocaleInTime.java new file mode 100644 index 00000000000..dd942680d2e --- /dev/null +++ b/jdk/test/sun/security/util/DerOutputStream/LocaleInTime.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * 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 6670889 + * @summary Keystore created under Hindi Locale causing ArrayIndexOutOfBoundsException + * @run main/othervm -Duser.language=hi -Duser.region=IN LocaleInTime + */ + +import java.util.Date; +import sun.security.util.DerOutputStream; +import sun.security.util.DerValue; + +public class LocaleInTime { + public static void main(String args[]) throws Exception { + DerOutputStream out = new DerOutputStream(); + out.putUTCTime(new Date()); + DerValue val = new DerValue(out.toByteArray()); + System.out.println(val.getUTCTime()); + } +} From c3da61922777228c2f117b446e29befbcd06c131 Mon Sep 17 00:00:00 2001 From: Peter Zhelezniakov Date: Tue, 13 Jul 2010 17:26:34 +0400 Subject: [PATCH 05/56] 6462562: InternationalFormatter inserts text incorrectly 6578432: Currency format instance does not work with Swing's NumberFormatter Reviewed-by: rupashka --- .../javax/swing/text/DefaultFormatter.java | 4 +- .../swing/text/InternationalFormatter.java | 78 +--- .../JFormattedTextField/Test6462562.java | 360 ++++++++++++++++++ 3 files changed, 380 insertions(+), 62 deletions(-) create mode 100644 jdk/test/javax/swing/JFormattedTextField/Test6462562.java diff --git a/jdk/src/share/classes/javax/swing/text/DefaultFormatter.java b/jdk/src/share/classes/javax/swing/text/DefaultFormatter.java index d6e47c5fdf9..75c3481678e 100644 --- a/jdk/src/share/classes/javax/swing/text/DefaultFormatter.java +++ b/jdk/src/share/classes/javax/swing/text/DefaultFormatter.java @@ -570,7 +570,9 @@ public class DefaultFormatter extends JFormattedTextField.AbstractFormatter direction = -1; } - if (getOverwriteMode() && rh.text != null) { + if (getOverwriteMode() && rh.text != null && + getFormattedTextField().getSelectedText() == null) + { rh.length = Math.min(Math.max(rh.length, rh.text.length()), rh.fb.getDocument().getLength() - rh.offset); } diff --git a/jdk/src/share/classes/javax/swing/text/InternationalFormatter.java b/jdk/src/share/classes/javax/swing/text/InternationalFormatter.java index c511b20e281..b49fed2e3ce 100644 --- a/jdk/src/share/classes/javax/swing/text/InternationalFormatter.java +++ b/jdk/src/share/classes/javax/swing/text/InternationalFormatter.java @@ -622,18 +622,8 @@ public class InternationalFormatter extends DefaultFormatter { /** * Overriden in an attempt to honor the literals. - *

- * If we do - * not allow invalid values and are in overwrite mode, this does the - * following for each character in the replacement range: - *

    - *
  1. If the character is a literal, add it to the string to replace - * with. If there is text to insert and it doesn't match the - * literal, then insert the literal in the the middle of the insert - * text. This allows you to either paste in literals or not and - * get the same behavior. - *
  2. If there is no text to insert, replace it with ' '. - *
+ *

If we do not allow invalid values and are in overwrite mode, this + * {@code rh.length} is corrected as to preserve trailing literals. * If not in overwrite mode, and there is text to insert it is * inserted at the next non literal index going forward. If there * is only text to remove, it is removed from the next non literal @@ -643,61 +633,27 @@ public class InternationalFormatter extends DefaultFormatter { if (!getAllowsInvalid()) { String text = rh.text; int tl = (text != null) ? text.length() : 0; + JTextComponent c = getFormattedTextField(); - if (tl == 0 && rh.length == 1 && getFormattedTextField(). - getSelectionStart() != rh.offset) { + if (tl == 0 && rh.length == 1 && c.getSelectionStart() != rh.offset) { // Backspace, adjust to actually delete next non-literal. rh.offset = getNextNonliteralIndex(rh.offset, -1); - } - if (getOverwriteMode()) { - StringBuffer replace = null; + } else if (getOverwriteMode()) { + int pos = rh.offset; + int textPos = pos; + boolean overflown = false; - for (int counter = 0, textIndex = 0, - max = Math.max(tl, rh.length); counter < max; - counter++) { - if (isLiteral(rh.offset + counter)) { - if (replace != null) { - replace.append(getLiteral(rh.offset + - counter)); - } - if (textIndex < tl && text.charAt(textIndex) == - getLiteral(rh.offset + counter)) { - textIndex++; - } - else if (textIndex == 0) { - rh.offset++; - rh.length--; - counter--; - max--; - } - else if (replace == null) { - replace = new StringBuffer(max); - replace.append(text.substring(0, textIndex)); - replace.append(getLiteral(rh.offset + - counter)); - } - } - else if (textIndex < tl) { - if (replace != null) { - replace.append(text.charAt(textIndex)); - } - textIndex++; - } - else { - // Nothing to replace it with, assume ' ' - if (replace == null) { - replace = new StringBuffer(max); - if (textIndex > 0) { - replace.append(text.substring(0, textIndex)); - } - } - if (replace != null) { - replace.append(' '); - } + for (int i = 0; i < rh.length; i++) { + while (isLiteral(pos)) pos++; + if (pos >= string.length()) { + pos = textPos; + overflown = true; + break; } + textPos = ++pos; } - if (replace != null) { - rh.text = replace.toString(); + if (overflown || c.getSelectedText() == null) { + rh.length = pos - rh.offset; } } else if (tl > 0) { diff --git a/jdk/test/javax/swing/JFormattedTextField/Test6462562.java b/jdk/test/javax/swing/JFormattedTextField/Test6462562.java new file mode 100644 index 00000000000..0696a016fba --- /dev/null +++ b/jdk/test/javax/swing/JFormattedTextField/Test6462562.java @@ -0,0 +1,360 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @bug 6462562 + @summary Tests text input into JFormattedTextField + with an InternationalFormatter + @author Peter Zhelezniakov + @run main Test6462562 +*/ + +import java.awt.event.ActionEvent; +import java.text.DateFormat; +import java.text.NumberFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; +import javax.swing.Action; +import javax.swing.JFormattedTextField; +import javax.swing.SwingUtilities; +import javax.swing.text.Caret; +import javax.swing.text.DateFormatter; +import javax.swing.text.DefaultEditorKit; +import javax.swing.text.InternationalFormatter; +import javax.swing.text.NumberFormatter; + + +public class Test6462562 +{ + static final String BACKSPACE = new String("backspace"); + static final String DELETE = new String("delete"); + + boolean failed = false; + + void test() { + testPercentFormat(); + testCurrencyFormat(); + testIntegerFormat(); + testDateFormat(); + + if (failed) { + throw new RuntimeException("Some testcases failed, see output above"); + } + System.err.println("(-; All testcases passed ;-)"); + } + + TestFormattedTextField create(NumberFormat format) { + format.setMaximumFractionDigits(0); + NumberFormatter fmt = new NumberFormatter(format); + return new TestFormattedTextField(fmt); + } + + TestFormattedTextField create(DateFormat format) { + DateFormatter fmt = new DateFormatter(format); + return new TestFormattedTextField(fmt); + } + + public static void main(String[] args) throws Exception { + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + new Test6462562().test(); + } + }); + } + + class TestFormattedTextField extends JFormattedTextField + { + final Action backspace; + final Action delete; + final Action insert; + + final ActionEvent dummyEvent; + + public TestFormattedTextField(InternationalFormatter fmt) { + super(fmt); + fmt.setAllowsInvalid(false); + fmt.setOverwriteMode(true); + + backspace = getActionMap().get(DefaultEditorKit.deletePrevCharAction); + delete = getActionMap().get(DefaultEditorKit.deleteNextCharAction); + insert = getActionMap().get(DefaultEditorKit.insertContentAction); + dummyEvent = new ActionEvent(this, 0, null); + } + + public boolean test(int pos, int selectionLength, String todo, Object expectedResult) { + Object v0 = getValue(); + + Caret caret = getCaret(); + caret.setDot(pos); + if (selectionLength > 0) { + caret.moveDot(pos + selectionLength); + } + + String desc = todo; + if (todo == BACKSPACE) { + backspace.actionPerformed(dummyEvent); + } else if (todo == DELETE) { + delete.actionPerformed(dummyEvent); + } else { + desc = "insert('" + todo + "')"; + insert.actionPerformed(new ActionEvent(this, 0, todo)); + } + + try { + commitEdit(); + } catch (ParseException e) { + e.printStackTrace(); + failed = true; + return false; + } + + Object v1 = getValue(); + if (! v1.equals(expectedResult)) { + System.err.printf("Failure: value='%s', mark=%d, dot=%d, action=%s\n", + v0, pos, pos + selectionLength, desc); + System.err.printf(" Result: '%s', expected: '%s'\n", v1, expectedResult); + failed = true; + return false; + } + return true; + } + } + + void testPercentFormat() { + NumberFormat format = NumberFormat.getPercentInstance(Locale.US); + TestFormattedTextField ftf = create(format); + ftf.setValue(.34); + + System.err.println("Testing NumberFormat.getPercentInstance(Locale.US)"); + + // test inserting individual characters + ftf.test(0, 0, "1", .14); + ftf.test(2, 0, "2", 1.42); + ftf.test(1, 0, "0", 1.02); + + // test inserting several characters at once - e.g. from clipboard + ftf.test(0, 0, "1024", 10.24); + ftf.test(3, 0, "333", 103.33); + ftf.test(6, 0, "77", 10333.77); + ftf.test(4, 0, "99", 10399.77); + ftf.test(6, 0, "00", 10390.07); + + // test inserting strings that contain some formatting + ftf.test(0, 0, "2,2", 2290.07); + ftf.test(2, 0, "2,2", 222.27); + ftf.test(4, 0, "2,2", 222.22); + ftf.test(6, 0, "33,33", 2222233.33); + + // test delete + ftf.test(0, 0, DELETE, 222233.33); + ftf.test(10, 0, DELETE, 222233.33); + ftf.test(5, 0, DELETE, 22223.33); + ftf.test(6, 0, DELETE, 2222.33); + + // test backspace + ftf.test(0, 0, BACKSPACE, 2222.33); + ftf.test(7, 0, BACKSPACE, 222.23); + ftf.test(4, 0, BACKSPACE, 22.23); + ftf.test(2, 0, BACKSPACE, 2.23); + + // test replacing selection + ftf.test(0, 1, "555", 555.23); + ftf.test(4, 2, "555", 5555.55); + ftf.test(2, 3, "1", 551.55); + ftf.test(3, 2, "6", 55.65); + ftf.test(4, 2, "12", 556.12); + ftf.test(3, 4, "0", 5.5); + ftf.test(0, 3, "111222333444555", 1112223334445.55); + + // test deleting selection + ftf.test(0, 2, DELETE, 12223334445.55); + ftf.test(0, 3, BACKSPACE, 223334445.55); + ftf.test(12, 2, DELETE, 2233344.45); + ftf.test(9, 2, BACKSPACE, 22333.44); + ftf.test(4, 3, DELETE, 223.44); + ftf.test(1, 2, BACKSPACE, 23.44); + ftf.test(3, 3, DELETE, .23); + ftf.test(1, 2, BACKSPACE, .02); + } + + void testCurrencyFormat() { + NumberFormat format = NumberFormat.getCurrencyInstance(Locale.US); + TestFormattedTextField ftf = create(format); + ftf.setValue(56L); + + System.err.println("Testing NumberFormat.getCurrencyInstance(Locale.US)"); + + // test inserting individual characters + ftf.test(1, 0, "1", 16L); + ftf.test(3, 0, "2", 162L); + ftf.test(2, 0, "0", 102L); + + // test inserting several characters at once - e.g. from clipboard + ftf.test(1, 0, "1024", 1024L); + ftf.test(4, 0, "333", 10333L); + ftf.test(7, 0, "77", 1033377L); + ftf.test(5, 0, "99", 1039977L); + ftf.test(7, 0, "00", 1039007L); + + // test inserting strings that contain some formatting + ftf.test(1, 0, "2,2", 229007L); + ftf.test(3, 0, "2,2", 22227L); + ftf.test(4, 0, "2,2", 2222L); + ftf.test(6, 0, "33,33", 22223333L); + + // test delete + ftf.test(1, 0, DELETE, 2223333L); + ftf.test(10, 0, DELETE, 2223333L); + ftf.test(5, 0, DELETE, 222333L); + ftf.test(5, 0, DELETE, 22233L); + + // test backspace + ftf.test(1, 0, BACKSPACE, 22233L); + ftf.test(7, 0, BACKSPACE, 2223L); + ftf.test(4, 0, BACKSPACE, 223L); + ftf.test(2, 0, BACKSPACE, 23L); + + // test replacing selection + ftf.test(1, 1, "555", 5553L); + ftf.test(4, 2, "555", 55555L); + ftf.test(2, 3, "1", 5155L); + ftf.test(3, 2, "6", 565L); + ftf.test(1, 3, "111222333444555", 111222333444555L); + + // test deleting selection + ftf.test(1, 2, DELETE, 1222333444555L); + ftf.test(1, 3, BACKSPACE, 22333444555L); + ftf.test(13, 2, DELETE, 223334445L); + ftf.test(10, 2, BACKSPACE, 2233344L); + ftf.test(4, 4, DELETE, 2244L); + ftf.test(1, 4, BACKSPACE, 4L); + } + + void testIntegerFormat() { + NumberFormat format = NumberFormat.getIntegerInstance(Locale.US); + TestFormattedTextField ftf = create(format); + ftf.setValue(56L); + + System.err.println("Testing NumberFormat.getIntegerInstance(Locale.US)"); + + // test inserting individual characters + ftf.test(0, 0, "1", 16L); + ftf.test(2, 0, "2", 162L); + ftf.test(1, 0, "0", 102L); + + // test inserting several characters at once - e.g. from clipboard + ftf.test(0, 0, "1024", 1024L); + ftf.test(3, 0, "333", 10333L); + ftf.test(6, 0, "77", 1033377L); + ftf.test(4, 0, "99", 1039977L); + ftf.test(6, 0, "00", 1039007L); + + // test inserting strings that contain some formatting + ftf.test(0, 0, "2,2", 229007L); + ftf.test(2, 0, "2,2", 22227L); + ftf.test(3, 0, "2,2", 2222L); + ftf.test(5, 0, "33,33", 22223333L); + + // test delete + ftf.test(0, 0, DELETE, 2223333L); + ftf.test(9, 0, DELETE, 2223333L); + ftf.test(4, 0, DELETE, 222333L); + ftf.test(4, 0, DELETE, 22233L); + + // test backspace + ftf.test(0, 0, BACKSPACE, 22233L); + ftf.test(6, 0, BACKSPACE, 2223L); + ftf.test(2, 0, BACKSPACE, 223L); + ftf.test(2, 0, BACKSPACE, 23L); + + // test replacing selection + ftf.test(0, 1, "555", 5553L); + ftf.test(3, 2, "555", 55555L); + ftf.test(1, 3, "1", 5155L); + ftf.test(2, 2, "6", 565L); + ftf.test(0, 3, "111222333444555", 111222333444555L); + + // test deleting selection + ftf.test(0, 2, DELETE, 1222333444555L); + ftf.test(0, 3, BACKSPACE, 22333444555L); + ftf.test(12, 2, DELETE, 223334445L); + ftf.test(9, 2, BACKSPACE, 2233344L); + ftf.test(3, 4, DELETE, 2244L); + ftf.test(0, 4, BACKSPACE, 4L); + } + + Date date(DateFormat format, String spec) { + try { + return format.parse(spec); + } catch (ParseException e) { + throw new Error("Error in test"); + } + } + + void testDateFormat() { + DateFormat format = new SimpleDateFormat("MM/dd/yyyy", Locale.US); + TestFormattedTextField ftf = create(format); + ftf.setValue(date(format, "12/05/2005")); + + System.err.println("Testing SimpleDateFormat(\"MM/dd/yyyy\", Locale.US)"); + + // test inserting individual characters + ftf.test(0, 0, "0", date(format, "02/05/2005")); + ftf.test(4, 0, "4", date(format, "02/04/2005")); + ftf.test(6, 0, "1", date(format, "02/04/1005")); + ftf.test(9, 0, "9", date(format, "02/04/1009")); + + // test inserting several characters at once - e.g. from clipboard + ftf.test(0, 0, "11", date(format, "11/04/1009")); + ftf.test(3, 0, "23", date(format, "11/23/1009")); + ftf.test(6, 0, "191", date(format, "11/23/1919")); + + // test delete + ftf.test(0, 0, DELETE, date(format, "01/23/1919")); + ftf.test(3, 0, DELETE, date(format, "01/03/1919")); + ftf.test(10, 0, DELETE, date(format, "01/03/1919")); + ftf.test(1, 0, DELETE, date(format, "12/03/1918")); + ftf.test(4, 0, DELETE, date(format, "11/30/1918")); + + // test backspace + ftf.test(0, 0, BACKSPACE, date(format, "11/30/1918")); + ftf.test(1, 0, BACKSPACE, date(format, "01/30/1918")); + ftf.test(4, 0, BACKSPACE, date(format, "12/31/1917")); + ftf.test(10, 0, BACKSPACE, date(format, "12/31/0191")); + ftf.test(3, 0, BACKSPACE, date(format, "01/31/0191")); + ftf.test(5, 0, BACKSPACE, date(format, "01/03/0191")); + + // test replacing selection + ftf.test(0, 1, "1", date(format, "11/03/0191")); + ftf.test(3, 1, "2", date(format, "11/23/0191")); + ftf.test(6, 2, "20", date(format, "11/23/2091")); + + // test deleting selection + ftf.test(0, 1, BACKSPACE, date(format, "01/23/2091")); + ftf.test(3, 1, DELETE, date(format, "01/03/2091")); + ftf.test(6, 2, BACKSPACE, date(format, "01/03/0091")); + ftf.test(8, 1, DELETE, date(format, "01/03/0001")); + } +} From 7dcb52915b45ad916c7631fa71368613dfaa6224 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Thu, 15 Jul 2010 18:02:05 -0700 Subject: [PATCH 06/56] 6963622: Project Coin: Refinements to suppressed exceptions Reviewed-by: alanb, forax, jjb --- .../classes/java/lang/AutoCloseable.java | 7 + .../share/classes/java/lang/Throwable.java | 124 ++++++++++-------- .../lang/Throwable/SuppressedExceptions.java | 16 ++- 3 files changed, 90 insertions(+), 57 deletions(-) diff --git a/jdk/src/share/classes/java/lang/AutoCloseable.java b/jdk/src/share/classes/java/lang/AutoCloseable.java index 0f7ed8e0dd6..18c28fe887b 100644 --- a/jdk/src/share/classes/java/lang/AutoCloseable.java +++ b/jdk/src/share/classes/java/lang/AutoCloseable.java @@ -41,6 +41,13 @@ public interface AutoCloseable { * be declared to throw more specific exceptions (or no exception * at all, if the close cannot fail). * + *

Note that unlike the {@link java.io.Closeable#close close} + * method of {@link java.io.Closeable}, this {@code close} method + * is not required to be idempotent. In other words, + * calling this {@code close} method more than once may have some + * visible side effect, unlike {@code Closeable.close} which is + * required to have no effect if called more than once. + * * @throws Exception if this resource cannot be closed */ void close() throws Exception; diff --git a/jdk/src/share/classes/java/lang/Throwable.java b/jdk/src/share/classes/java/lang/Throwable.java index 58478f90af4..213f5f86d5c 100644 --- a/jdk/src/share/classes/java/lang/Throwable.java +++ b/jdk/src/share/classes/java/lang/Throwable.java @@ -28,12 +28,12 @@ import java.io.*; import java.util.*; /** - * The Throwable class is the superclass of all errors and + * The {@code Throwable} class is the superclass of all errors and * exceptions in the Java language. Only objects that are instances of this * class (or one of its subclasses) are thrown by the Java Virtual Machine or - * can be thrown by the Java throw statement. Similarly, only + * can be thrown by the Java {@code throw} statement. Similarly, only * this class or one of its subclasses can be the argument type in a - * catch clause. + * {@code catch} clause. * * For the purposes of compile-time checking of exceptions, {@code * Throwable} and any subclass of {@code Throwable} that is not also a @@ -73,11 +73,11 @@ import java.util.*; * permit the method to throw the cause directly. For example, suppose * a persistent collection conforms to the {@link java.util.Collection * Collection} interface, and that its persistence is implemented atop - * java.io. Suppose the internals of the add method + * {@code java.io}. Suppose the internals of the {@code add} method * can throw an {@link java.io.IOException IOException}. The implementation - * can communicate the details of the IOException to its caller - * while conforming to the Collection interface by wrapping the - * IOException in an appropriate unchecked exception. (The + * can communicate the details of the {@code IOException} to its caller + * while conforming to the {@code Collection} interface by wrapping the + * {@code IOException} in an appropriate unchecked exception. (The * specification for the persistent collection should indicate that it is * capable of throwing such exceptions.) * @@ -86,7 +86,7 @@ import java.util.*; * {@link #initCause(Throwable)} method. New throwable classes that * wish to allow causes to be associated with them should provide constructors * that take a cause and delegate (perhaps indirectly) to one of the - * Throwable constructors that takes a cause. For example: + * {@code Throwable} constructors that takes a cause. For example: *

  *     try {
  *         lowLevelOp();
@@ -94,10 +94,10 @@ import  java.util.*;
  *         throw new HighLevelException(le);  // Chaining-aware constructor
  *     }
  * 
- * Because the initCause method is public, it allows a cause to be + * Because the {@code initCause} method is public, it allows a cause to be * associated with any throwable, even a "legacy throwable" whose * implementation predates the addition of the exception chaining mechanism to - * Throwable. For example: + * {@code Throwable}. For example: *
  *     try {
  *         lowLevelOp();
@@ -121,28 +121,28 @@ import  java.util.*;
  * use the standard exception chaining mechanism, while continuing to
  * implement their "legacy" chaining mechanisms for compatibility.
  *
- * 

Further, as of release 1.4, many general purpose Throwable + *

Further, as of release 1.4, many general purpose {@code Throwable} * classes (for example {@link Exception}, {@link RuntimeException}, * {@link Error}) have been retrofitted with constructors that take * a cause. This was not strictly necessary, due to the existence of the - * initCause method, but it is more convenient and expressive to + * {@code initCause} method, but it is more convenient and expressive to * delegate to a constructor that takes a cause. * - *

By convention, class Throwable and its subclasses have two + *

By convention, class {@code Throwable} and its subclasses have two * constructors, one that takes no arguments and one that takes a - * String argument that can be used to produce a detail message. + * {@code String} argument that can be used to produce a detail message. * Further, those subclasses that might likely have a cause associated with * them should have two more constructors, one that takes a - * Throwable (the cause), and one that takes a - * String (the detail message) and a Throwable (the + * {@code Throwable} (the cause), and one that takes a + * {@code String} (the detail message) and a {@code Throwable} (the * cause). * *

Also introduced in release 1.4 is the {@link #getStackTrace()} method, * which allows programmatic access to the stack trace information that was * previously available only in text form, via the various forms of the * {@link #printStackTrace()} method. This information has been added to the - * serialized representation of this class so getStackTrace - * and printStackTrace will operate properly on a throwable that + * serialized representation of this class so {@code getStackTrace} + * and {@code printStackTrace} will operate properly on a throwable that * was obtained by deserialization. * * @author unascribed @@ -162,7 +162,7 @@ public class Throwable implements Serializable { /** * Specific details about the Throwable. For example, for - * FileNotFoundException, this contains the name of + * {@code FileNotFoundException}, this contains the name of * the file that could not be found. * * @serial @@ -212,7 +212,7 @@ public class Throwable implements Serializable { private static final String SUPPRESSED_CAPTION = "Suppressed: "; /** - * Constructs a new throwable with null as its detail message. + * Constructs a new throwable with {@code null} as its detail message. * The cause is not initialized, and may subsequently be initialized by a * call to {@link #initCause}. * @@ -242,7 +242,7 @@ public class Throwable implements Serializable { /** * Constructs a new throwable with the specified detail message and * cause.

Note that the detail message associated with - * cause is not automatically incorporated in + * {@code cause} is not automatically incorporated in * this throwable's detail message. * *

The {@link #fillInStackTrace()} method is called to initialize @@ -251,7 +251,7 @@ public class Throwable implements Serializable { * @param message the detail message (which is saved for later retrieval * by the {@link #getMessage()} method). * @param cause the cause (which is saved for later retrieval by the - * {@link #getCause()} method). (A null value is + * {@link #getCause()} method). (A {@code null} value is * permitted, and indicates that the cause is nonexistent or * unknown.) * @since 1.4 @@ -264,8 +264,8 @@ public class Throwable implements Serializable { /** * Constructs a new throwable with the specified cause and a detail - * message of (cause==null ? null : cause.toString()) (which - * typically contains the class and detail message of cause). + * message of {@code (cause==null ? null : cause.toString())} (which + * typically contains the class and detail message of {@code cause}). * This constructor is useful for throwables that are little more than * wrappers for other throwables (for example, {@link * java.security.PrivilegedActionException}). @@ -274,7 +274,7 @@ public class Throwable implements Serializable { * the stack trace data in the newly created throwable. * * @param cause the cause (which is saved for later retrieval by the - * {@link #getCause()} method). (A null value is + * {@link #getCause()} method). (A {@code null} value is * permitted, and indicates that the cause is nonexistent or * unknown.) * @since 1.4 @@ -288,8 +288,8 @@ public class Throwable implements Serializable { /** * Returns the detail message string of this throwable. * - * @return the detail message string of this Throwable instance - * (which may be null). + * @return the detail message string of this {@code Throwable} instance + * (which may be {@code null}). */ public String getMessage() { return detailMessage; @@ -300,7 +300,7 @@ public class Throwable implements Serializable { * Subclasses may override this method in order to produce a * locale-specific message. For subclasses that do not override this * method, the default implementation returns the same result as - * getMessage(). + * {@code getMessage()}. * * @return The localized description of this throwable. * @since JDK1.1 @@ -310,22 +310,22 @@ public class Throwable implements Serializable { } /** - * Returns the cause of this throwable or null if the + * Returns the cause of this throwable or {@code null} if the * cause is nonexistent or unknown. (The cause is the throwable that * caused this throwable to get thrown.) * *

This implementation returns the cause that was supplied via one of - * the constructors requiring a Throwable, or that was set after + * the constructors requiring a {@code Throwable}, or that was set after * creation with the {@link #initCause(Throwable)} method. While it is * typically unnecessary to override this method, a subclass can override * it to return a cause set by some other means. This is appropriate for * a "legacy chained throwable" that predates the addition of chained - * exceptions to Throwable. Note that it is not - * necessary to override any of the PrintStackTrace methods, - * all of which invoke the getCause method to determine the + * exceptions to {@code Throwable}. Note that it is not + * necessary to override any of the {@code PrintStackTrace} methods, + * all of which invoke the {@code getCause} method to determine the * cause of a throwable. * - * @return the cause of this throwable or null if the + * @return the cause of this throwable or {@code null} if the * cause is nonexistent or unknown. * @since 1.4 */ @@ -345,11 +345,11 @@ public class Throwable implements Serializable { * even once. * * @param cause the cause (which is saved for later retrieval by the - * {@link #getCause()} method). (A null value is + * {@link #getCause()} method). (A {@code null} value is * permitted, and indicates that the cause is nonexistent or * unknown.) - * @return a reference to this Throwable instance. - * @throws IllegalArgumentException if cause is this + * @return a reference to this {@code Throwable} instance. + * @throws IllegalArgumentException if {@code cause} is this * throwable. (A throwable cannot be its own cause.) * @throws IllegalStateException if this throwable was * created with {@link #Throwable(Throwable)} or @@ -375,7 +375,7 @@ public class Throwable implements Serializable { *

  • the result of invoking this object's {@link #getLocalizedMessage} * method * - * If getLocalizedMessage returns null, then just + * If {@code getLocalizedMessage} returns {@code null}, then just * the class name is returned. * * @return a string representation of this throwable. @@ -389,8 +389,8 @@ public class Throwable implements Serializable { /** * Prints this throwable and its backtrace to the * standard error stream. This method prints a stack trace for this - * Throwable object on the error output stream that is - * the value of the field System.err. The first line of + * {@code Throwable} object on the error output stream that is + * the value of the field {@code System.err}. The first line of * output contains the result of the {@link #toString()} method for * this object. Remaining lines represent data previously recorded by * the method {@link #fillInStackTrace()}. The format of this @@ -435,7 +435,7 @@ public class Throwable implements Serializable { * at Junk.c(Junk.java:21) * ... 3 more *
  • - * Note the presence of lines containing the characters "...". + * Note the presence of lines containing the characters {@code "..."}. * These lines indicate that the remainder of the stack trace for this * exception matches the indicated number of frames from the bottom of the * stack trace of the exception that was caused by this exception (the @@ -542,14 +542,17 @@ public class Throwable implements Serializable { /** * Prints this throwable and its backtrace to the specified print stream. * - * @param s PrintStream to use for output + * @param s {@code PrintStream} to use for output */ public void printStackTrace(PrintStream s) { printStackTrace(new WrappedPrintStream(s)); } private void printStackTrace(PrintStreamOrWriter s) { - Set dejaVu = new HashSet(); + // Guard against malicious overrides of Throwable.equals by + // using a Set with identity equality semantics. + Set dejaVu = + Collections.newSetFromMap(new IdentityHashMap()); dejaVu.add(this); synchronized (s.lock()) { @@ -616,7 +619,7 @@ public class Throwable implements Serializable { * Prints this throwable and its backtrace to the specified * print writer. * - * @param s PrintWriter to use for output + * @param s {@code PrintWriter} to use for output * @since JDK1.1 */ public void printStackTrace(PrintWriter s) { @@ -669,10 +672,10 @@ public class Throwable implements Serializable { /** * Fills in the execution stack trace. This method records within this - * Throwable object information about the current state of + * {@code Throwable} object information about the current state of * the stack frames for the current thread. * - * @return a reference to this Throwable instance. + * @return a reference to this {@code Throwable} instance. * @see java.lang.Throwable#printStackTrace() */ public synchronized native Throwable fillInStackTrace(); @@ -694,7 +697,7 @@ public class Throwable implements Serializable { * this throwable is permitted to return a zero-length array from this * method. Generally speaking, the array returned by this method will * contain one element for every frame that would be printed by - * printStackTrace. + * {@code printStackTrace}. * * @return an array of stack trace elements representing the stack trace * pertaining to this throwable. @@ -727,14 +730,14 @@ public class Throwable implements Serializable { * read from a serialization stream. * * @param stackTrace the stack trace elements to be associated with - * this Throwable. The specified array is copied by this + * this {@code Throwable}. The specified array is copied by this * call; changes in the specified array after the method invocation - * returns will have no affect on this Throwable's stack + * returns will have no affect on this {@code Throwable}'s stack * trace. * - * @throws NullPointerException if stackTrace is - * null, or if any of the elements of - * stackTrace are null + * @throws NullPointerException if {@code stackTrace} is + * {@code null}, or if any of the elements of + * {@code stackTrace} are {@code null} * * @since 1.4 */ @@ -761,8 +764,8 @@ public class Throwable implements Serializable { * package-protection for use by SharedSecrets. * * @param index index of the element to return. - * @throws IndexOutOfBoundsException if index < 0 || - * index >= getStackTraceDepth() + * @throws IndexOutOfBoundsException if {@code index < 0 || + * index >= getStackTraceDepth() } */ native StackTraceElement getStackTraceElement(int index); @@ -794,14 +797,27 @@ public class Throwable implements Serializable { * were suppressed, typically by the automatic resource management * statement, in order to deliver this exception. * + *

    Note that when one exception {@linkplain + * #initCause(Throwable) causes} another exception, the first + * exception is usually caught and then the second exception is + * thrown in response. In contrast, when one exception suppresses + * another, two exceptions are thrown in sibling code blocks, such + * as in a {@code try} block and in its {@code finally} block, and + * control flow can only continue with one exception so the second + * is recorded as a suppressed exception of the first. + * * @param exception the exception to be added to the list of * suppressed exceptions * @throws NullPointerException if {@code exception} is null + * @throws IllegalArgumentException if {@code exception} is this + * throwable; a throwable cannot suppress itself. * @since 1.7 */ public synchronized void addSuppressedException(Throwable exception) { if (exception == null) throw new NullPointerException(NULL_CAUSE_MESSAGE); + if (exception == this) + throw new IllegalArgumentException("Self-suppression not permitted"); if (suppressedExceptions.size() == 0) suppressedExceptions = new ArrayList(); diff --git a/jdk/test/java/lang/Throwable/SuppressedExceptions.java b/jdk/test/java/lang/Throwable/SuppressedExceptions.java index 89f974c0f4f..0993cd6333f 100644 --- a/jdk/test/java/lang/Throwable/SuppressedExceptions.java +++ b/jdk/test/java/lang/Throwable/SuppressedExceptions.java @@ -26,7 +26,7 @@ import java.util.*; /* * @test - * @bug 6911258 6962571 + * @bug 6911258 6962571 6963622 * @summary Basic tests of suppressed exceptions * @author Joseph D. Darcy */ @@ -35,11 +35,22 @@ public class SuppressedExceptions { private static String message = "Bad suppressed exception information"; public static void main(String... args) throws Exception { + noSelfSuppression(); basicSupressionTest(); serializationTest(); selfReference(); } + private static void noSelfSuppression() { + Throwable throwable = new Throwable(); + try { + throwable.addSuppressedException(throwable); + throw new RuntimeException("IllegalArgumentException for self-suppresion not thrown."); + } catch (IllegalArgumentException iae) { + ; // Expected + } + } + private static void basicSupressionTest() { Throwable throwable = new Throwable(); RuntimeException suppressed = new RuntimeException("A suppressed exception."); @@ -156,9 +167,8 @@ public class SuppressedExceptions { throwable1.printStackTrace(); - - throwable1.addSuppressedException(throwable1); throwable1.addSuppressedException(throwable2); + throwable2.addSuppressedException(throwable1); throwable1.printStackTrace(); } From a4e41493406de39a5a1ba8565d94a569a9e59880 Mon Sep 17 00:00:00 2001 From: John R Rose Date: Thu, 15 Jul 2010 18:40:45 -0700 Subject: [PATCH 07/56] 6964498: JSR 292 invokedynamic sites need local bootstrap methods Add JVM_CONSTANT_InvokeDynamic records to constant pool to determine per-instruction BSMs. Reviewed-by: twisti --- .../sun/jvm/hotspot/oops/ConstantPool.java | 14 ++++ .../jvm/hotspot/runtime/ClassConstants.java | 1 + .../jvm/hotspot/tools/jcore/ClassWriter.java | 21 ++++-- .../ui/classbrowser/HTMLGenerator.java | 5 ++ .../jvm/hotspot/utilities/ConstantTag.java | 2 + .../share/vm/classfile/classFileParser.cpp | 36 +++++++++- .../share/vm/classfile/systemDictionary.cpp | 65 ++++++++++++++++--- .../share/vm/classfile/systemDictionary.hpp | 5 +- hotspot/src/share/vm/classfile/verifier.cpp | 3 +- .../share/vm/interpreter/bytecodeTracer.cpp | 17 ++++- .../vm/interpreter/interpreterRuntime.cpp | 25 +++---- .../src/share/vm/interpreter/linkResolver.cpp | 24 ++++++- .../src/share/vm/interpreter/linkResolver.hpp | 1 + hotspot/src/share/vm/interpreter/rewriter.cpp | 27 ++++++++ hotspot/src/share/vm/interpreter/rewriter.hpp | 17 +++++ .../src/share/vm/oops/constantPoolKlass.cpp | 4 ++ hotspot/src/share/vm/oops/constantPoolOop.cpp | 39 ++++++++++- hotspot/src/share/vm/oops/constantPoolOop.hpp | 15 +++++ hotspot/src/share/vm/oops/cpCacheOop.cpp | 45 +++++++++++-- hotspot/src/share/vm/oops/cpCacheOop.hpp | 5 ++ hotspot/src/share/vm/prims/jvm.h | 3 +- hotspot/src/share/vm/prims/methodHandles.cpp | 4 ++ hotspot/src/share/vm/runtime/globals.hpp | 3 + .../src/share/vm/utilities/constantTag.cpp | 2 + .../src/share/vm/utilities/constantTag.hpp | 3 +- 25 files changed, 340 insertions(+), 46 deletions(-) diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPool.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPool.java index 58e199089ef..27872450487 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPool.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPool.java @@ -297,6 +297,7 @@ public class ConstantPool extends Oop implements ClassConstants { case JVM_CONSTANT_NameAndType: return "JVM_CONSTANT_NameAndType"; case JVM_CONSTANT_MethodHandle: return "JVM_CONSTANT_MethodHandle"; case JVM_CONSTANT_MethodType: return "JVM_CONSTANT_MethodType"; + case JVM_CONSTANT_InvokeDynamic: return "JVM_CONSTANT_InvokeDynamic"; case JVM_CONSTANT_Invalid: return "JVM_CONSTANT_Invalid"; case JVM_CONSTANT_UnresolvedClass: return "JVM_CONSTANT_UnresolvedClass"; case JVM_CONSTANT_UnresolvedClassInError: return "JVM_CONSTANT_UnresolvedClassInError"; @@ -355,6 +356,7 @@ public class ConstantPool extends Oop implements ClassConstants { case JVM_CONSTANT_NameAndType: case JVM_CONSTANT_MethodHandle: case JVM_CONSTANT_MethodType: + case JVM_CONSTANT_InvokeDynamic: visitor.doInt(new IntField(new NamedFieldIdentifier(nameForTag(ctag)), indexOffset(index), true), true); break; } @@ -517,6 +519,18 @@ public class ConstantPool extends Oop implements ClassConstants { + ", type = " + signatureIndex); break; } + + case JVM_CONSTANT_InvokeDynamic: { + dos.writeByte(cpConstType); + int value = getIntAt(ci); + short bootstrapMethodIndex = (short) extractLowShortFromInt(value); + short nameAndTypeIndex = (short) extractHighShortFromInt(value); + dos.writeShort(bootstrapMethodIndex); + dos.writeShort(nameAndTypeIndex); + if (DEBUG) debugMessage("CP[" + ci + "] = indy BSM = " + bootstrapMethodIndex + + ", N&T = " + nameAndTypeIndex); + break; + } default: throw new InternalError("unknown tag: " + cpConstType); } // switch diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/ClassConstants.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/ClassConstants.java index 889e9dc08b7..ff7db309fe9 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/ClassConstants.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/ClassConstants.java @@ -42,6 +42,7 @@ public interface ClassConstants public static final int JVM_CONSTANT_NameAndType = 12; public static final int JVM_CONSTANT_MethodHandle = 15; public static final int JVM_CONSTANT_MethodType = 16; + public static final int JVM_CONSTANT_InvokeDynamic = 17; // JVM_CONSTANT_MethodHandle subtypes public static final int JVM_REF_getField = 1; diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/jcore/ClassWriter.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/jcore/ClassWriter.java index 99ffaedc8eb..31f37a5df46 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/jcore/ClassWriter.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/jcore/ClassWriter.java @@ -303,12 +303,12 @@ public class ClassWriter implements /* imports */ ClassConstants case JVM_CONSTANT_MethodHandle: { dos.writeByte(cpConstType); int value = cpool.getIntAt(ci); - short refIndex = (short) extractHighShortFromInt(value); - byte refKind = (byte) extractLowShortFromInt(value); - dos.writeByte(refKind); - dos.writeShort(refIndex); - if (DEBUG) debugMessage("CP[" + ci + "] = MH index = " + refIndex - + ", kind = " + refKind); + short bootstrapMethodIndex = (short) extractLowShortFromInt(value); + short nameAndTypeIndex = (short) extractHighShortFromInt(value); + dos.writeShort(bootstrapMethodIndex); + dos.writeShort(nameAndTypeIndex); + if (DEBUG) debugMessage("CP[" + ci + "] = indy BSM = " + + bootstrapMethodIndex + ", N&T = " + nameAndTypeIndex); break; } @@ -321,6 +321,15 @@ public class ClassWriter implements /* imports */ ClassConstants break; } + case JVM_CONSTANT_InvokeDynamic: { + dos.writeByte(cpConstType); + int value = cpool.getIntAt(ci); + short refIndex = (short) value; + dos.writeShort(refIndex); + if (DEBUG) debugMessage("CP[" + ci + "] = MT index = " + refIndex); + break; + } + default: throw new InternalError("Unknown tag: " + cpConstType); } // switch diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java index 8ef0d8c4d42..d594404f414 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java @@ -582,6 +582,11 @@ public class HTMLGenerator implements /* imports */ ClassConstants { buf.cell(Integer.toString(cpool.getIntAt(index))); break; + case JVM_CONSTANT_InvokeDynamic: + buf.cell("JVM_CONSTANT_InvokeDynamic"); + buf.cell(genLowHighShort(cpool.getIntAt(index))); + break; + default: throw new InternalError("unknown tag: " + ctag); } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/ConstantTag.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/ConstantTag.java index 2a710c2a002..3f2baf3d9cc 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/ConstantTag.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/ConstantTag.java @@ -40,6 +40,7 @@ public class ConstantTag { private static int JVM_CONSTANT_NameAndType = 12; private static int JVM_CONSTANT_MethodHandle = 15; // JSR 292 private static int JVM_CONSTANT_MethodType = 16; // JSR 292 + private static int JVM_CONSTANT_InvokeDynamic = 17; // JSR 292 private static int JVM_CONSTANT_Invalid = 0; // For bad value initialization private static int JVM_CONSTANT_UnresolvedClass = 100; // Temporary tag until actual use private static int JVM_CONSTANT_ClassIndex = 101; // Temporary tag while constructing constant pool @@ -78,6 +79,7 @@ public class ConstantTag { public boolean isUtf8() { return tag == JVM_CONSTANT_Utf8; } public boolean isMethodHandle() { return tag == JVM_CONSTANT_MethodHandle; } public boolean isMethodType() { return tag == JVM_CONSTANT_MethodType; } + public boolean isInvokeDynamic() { return tag == JVM_CONSTANT_InvokeDynamic; } public boolean isInvalid() { return tag == JVM_CONSTANT_Invalid; } diff --git a/hotspot/src/share/vm/classfile/classFileParser.cpp b/hotspot/src/share/vm/classfile/classFileParser.cpp index 73fd78c7b98..f9c1d637c83 100644 --- a/hotspot/src/share/vm/classfile/classFileParser.cpp +++ b/hotspot/src/share/vm/classfile/classFileParser.cpp @@ -122,7 +122,7 @@ void ClassFileParser::parse_constant_pool_entries(constantPoolHandle cp, int len if (!EnableMethodHandles || _major_version < Verifier::INVOKEDYNAMIC_MAJOR_VERSION) { classfile_parse_error( - (!EnableInvokeDynamic ? + (!EnableMethodHandles ? "This JVM does not support constant tag %u in class file %s" : "Class file version does not support constant tag %u in class file %s"), tag, CHECK); @@ -140,6 +140,22 @@ void ClassFileParser::parse_constant_pool_entries(constantPoolHandle cp, int len ShouldNotReachHere(); } break; + case JVM_CONSTANT_InvokeDynamic : + { + if (!EnableInvokeDynamic || + _major_version < Verifier::INVOKEDYNAMIC_MAJOR_VERSION) { + classfile_parse_error( + (!EnableInvokeDynamic ? + "This JVM does not support constant tag %u in class file %s" : + "Class file version does not support constant tag %u in class file %s"), + tag, CHECK); + } + cfs->guarantee_more(5, CHECK); // bsm_index, name_and_type_index, tag/access_flags + u2 bootstrap_method_index = cfs->get_u2_fast(); + u2 name_and_type_index = cfs->get_u2_fast(); + cp->invoke_dynamic_at_put(index, bootstrap_method_index, name_and_type_index); + } + break; case JVM_CONSTANT_Integer : { cfs->guarantee_more(5, CHECK); // bytes, tag/access_flags @@ -414,6 +430,24 @@ constantPoolHandle ClassFileParser::parse_constant_pool(TRAPS) { ref_index, CHECK_(nullHandle)); } break; + case JVM_CONSTANT_InvokeDynamic : + { + int bootstrap_method_ref_index = cp->invoke_dynamic_bootstrap_method_ref_index_at(index); + int name_and_type_ref_index = cp->invoke_dynamic_name_and_type_ref_index_at(index); + check_property((bootstrap_method_ref_index == 0 && AllowTransitionalJSR292) + || + (valid_cp_range(bootstrap_method_ref_index, length) && + cp->tag_at(bootstrap_method_ref_index).is_method_handle()), + "Invalid constant pool index %u in class file %s", + bootstrap_method_ref_index, + CHECK_(nullHandle)); + check_property(valid_cp_range(name_and_type_ref_index, length) && + cp->tag_at(name_and_type_ref_index).is_name_and_type(), + "Invalid constant pool index %u in class file %s", + name_and_type_ref_index, + CHECK_(nullHandle)); + break; + } default: fatal(err_msg("bad constant pool tag value %u", cp->tag_at(index).value())); diff --git a/hotspot/src/share/vm/classfile/systemDictionary.cpp b/hotspot/src/share/vm/classfile/systemDictionary.cpp index 40c81427afe..fefe4d67c96 100644 --- a/hotspot/src/share/vm/classfile/systemDictionary.cpp +++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp @@ -2507,6 +2507,10 @@ Handle SystemDictionary::make_dynamic_call_site(Handle bootstrap_method, int caller_bci, TRAPS) { Handle empty; + guarantee(bootstrap_method.not_null() && + java_dyn_MethodHandle::is_instance(bootstrap_method()), + "caller must supply a valid BSM"); + Handle caller_mname = MethodHandles::new_MemberName(CHECK_(empty)); MethodHandles::init_MemberName(caller_mname(), caller_method()); @@ -2537,20 +2541,61 @@ Handle SystemDictionary::make_dynamic_call_site(Handle bootstrap_method, return call_site_oop; } -Handle SystemDictionary::find_bootstrap_method(KlassHandle caller, TRAPS) { +Handle SystemDictionary::find_bootstrap_method(methodHandle caller_method, int caller_bci, + int cache_index, TRAPS) { Handle empty; - if (!caller->oop_is_instance()) return empty; - instanceKlassHandle ik(THREAD, caller()); + constantPoolHandle pool; + { + klassOop caller = caller_method->method_holder(); + if (!Klass::cast(caller)->oop_is_instance()) return empty; + pool = constantPoolHandle(THREAD, instanceKlass::cast(caller)->constants()); + } - oop boot_method_oop = ik->bootstrap_method(); - if (boot_method_oop != NULL) { - if (TraceMethodHandles) { - tty->print_cr("bootstrap method for "PTR_FORMAT" cached as "PTR_FORMAT":", ik(), boot_method_oop); + int constant_pool_index = pool->cache()->entry_at(cache_index)->constant_pool_index(); + constantTag tag = pool->tag_at(constant_pool_index); + + if (tag.is_invoke_dynamic()) { + // JVM_CONSTANT_InvokeDynamic is an ordered pair of [bootm, name&type] + // The bootm, being a JVM_CONSTANT_MethodHandle, has its own cache entry. + int bsm_index = pool->invoke_dynamic_bootstrap_method_ref_index_at(constant_pool_index); + if (bsm_index != 0) { + int bsm_index_in_cache = pool->cache()->entry_at(cache_index)->bootstrap_method_index_in_cache(); + DEBUG_ONLY(int bsm_index_2 = pool->cache()->entry_at(bsm_index_in_cache)->constant_pool_index()); + assert(bsm_index == bsm_index_2, "BSM constant lifted to cache"); + if (TraceMethodHandles) { + tty->print_cr("resolving bootstrap method for "PTR_FORMAT" at %d at cache[%d]CP[%d]...", + (intptr_t) caller_method(), caller_bci, cache_index, constant_pool_index); + } + oop bsm_oop = pool->resolve_cached_constant_at(bsm_index_in_cache, CHECK_(empty)); + if (TraceMethodHandles) { + tty->print_cr("bootstrap method for "PTR_FORMAT" at %d retrieved as "PTR_FORMAT":", + (intptr_t) caller_method(), caller_bci, (intptr_t) bsm_oop); + } + assert(bsm_oop->is_oop() + && java_dyn_MethodHandle::is_instance(bsm_oop), "must be sane"); + return Handle(THREAD, bsm_oop); } - assert(boot_method_oop->is_oop() - && java_dyn_MethodHandle::is_instance(boot_method_oop), "must be sane"); - return Handle(THREAD, boot_method_oop); + // else null BSM; fall through + } else if (tag.is_name_and_type()) { + // JSR 292 EDR does not have JVM_CONSTANT_InvokeDynamic + // a bare name&type defaults its BSM to null, so fall through... + } else { + ShouldNotReachHere(); // verifier does not allow this + } + + // Fall through to pick up the per-class bootstrap method. + // This mechanism may go away in the PFD. + assert(AllowTransitionalJSR292, "else the verifier should have stopped us already"); + oop bsm_oop = instanceKlass::cast(caller_method->method_holder())->bootstrap_method(); + if (bsm_oop != NULL) { + if (TraceMethodHandles) { + tty->print_cr("bootstrap method for "PTR_FORMAT" registered as "PTR_FORMAT":", + (intptr_t) caller_method(), (intptr_t) bsm_oop); + } + assert(bsm_oop->is_oop() + && java_dyn_MethodHandle::is_instance(bsm_oop), "must be sane"); + return Handle(THREAD, bsm_oop); } return empty; diff --git a/hotspot/src/share/vm/classfile/systemDictionary.hpp b/hotspot/src/share/vm/classfile/systemDictionary.hpp index 56de18c42aa..11bf2257992 100644 --- a/hotspot/src/share/vm/classfile/systemDictionary.hpp +++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp @@ -492,7 +492,10 @@ public: TRAPS); // coordinate with Java about bootstrap methods - static Handle find_bootstrap_method(KlassHandle caller, TRAPS); + static Handle find_bootstrap_method(methodHandle caller_method, + int caller_bci, // N.B. must be an invokedynamic + int cache_index, // must be corresponding main_entry + TRAPS); // Utility for printing loader "name" as part of tracing constraints static const char* loader_name(oop loader) { diff --git a/hotspot/src/share/vm/classfile/verifier.cpp b/hotspot/src/share/vm/classfile/verifier.cpp index 603d4ec3c25..10072bd2e59 100644 --- a/hotspot/src/share/vm/classfile/verifier.cpp +++ b/hotspot/src/share/vm/classfile/verifier.cpp @@ -1913,7 +1913,8 @@ void ClassVerifier::verify_invoke_instructions( unsigned int types = (opcode == Bytecodes::_invokeinterface ? 1 << JVM_CONSTANT_InterfaceMethodref : opcode == Bytecodes::_invokedynamic - ? 1 << JVM_CONSTANT_NameAndType + ? (1 << JVM_CONSTANT_NameAndType + |1 << JVM_CONSTANT_InvokeDynamic) : 1 << JVM_CONSTANT_Methodref); verify_cp_type(index, cp, types, CHECK_VERIFY(this)); diff --git a/hotspot/src/share/vm/interpreter/bytecodeTracer.cpp b/hotspot/src/share/vm/interpreter/bytecodeTracer.cpp index 6fa807a4d86..1a5cadb4cc4 100644 --- a/hotspot/src/share/vm/interpreter/bytecodeTracer.cpp +++ b/hotspot/src/share/vm/interpreter/bytecodeTracer.cpp @@ -328,24 +328,35 @@ void BytecodePrinter::print_field_or_method(int orig_i, int i, outputStream* st) constantPoolOop constants = method()->constants(); constantTag tag = constants->tag_at(i); - int nt_index = -1; + bool has_klass = true; switch (tag.value()) { case JVM_CONSTANT_InterfaceMethodref: case JVM_CONSTANT_Methodref: case JVM_CONSTANT_Fieldref: + break; case JVM_CONSTANT_NameAndType: + case JVM_CONSTANT_InvokeDynamic: + has_klass = false; break; default: st->print_cr(" bad tag=%d at %d", tag.value(), i); return; } - symbolOop klass = constants->klass_name_at(constants->uncached_klass_ref_index_at(i)); symbolOop name = constants->uncached_name_ref_at(i); symbolOop signature = constants->uncached_signature_ref_at(i); const char* sep = (tag.is_field() ? "/" : ""); - st->print_cr(" %d <%s.%s%s%s> ", i, klass->as_C_string(), name->as_C_string(), sep, signature->as_C_string()); + if (has_klass) { + symbolOop klass = constants->klass_name_at(constants->uncached_klass_ref_index_at(i)); + st->print_cr(" %d <%s.%s%s%s> ", i, klass->as_C_string(), name->as_C_string(), sep, signature->as_C_string()); + } else { + if (tag.is_invoke_dynamic()) { + int bsm = constants->invoke_dynamic_bootstrap_method_ref_index_at(i); + st->print(" bsm=%d", bsm); + } + st->print_cr(" %d <%s%s%s>", i, name->as_C_string(), sep, signature->as_C_string()); + } } diff --git a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp index 2880a9ec2f9..c156bbb3792 100644 --- a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp +++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp @@ -702,10 +702,6 @@ IRT_ENTRY(void, InterpreterRuntime::resolve_invokedynamic(JavaThread* thread)) { methodHandle caller_method(thread, method(thread)); - // first find the bootstrap method - KlassHandle caller_klass(thread, caller_method->method_holder()); - Handle bootm = SystemDictionary::find_bootstrap_method(caller_klass, CHECK); - constantPoolHandle pool(thread, caller_method->constants()); pool->set_invokedynamic(); // mark header to flag active call sites @@ -726,7 +722,7 @@ IRT_ENTRY(void, InterpreterRuntime::resolve_invokedynamic(JavaThread* thread)) { CallInfo info; LinkResolver::resolve_invoke(info, Handle(), pool, site_index, bytecode, CHECK); - // The main entry corresponds to a JVM_CONSTANT_NameAndType, and serves + // The main entry corresponds to a JVM_CONSTANT_InvokeDynamic, and serves // as a common reference point for all invokedynamic call sites with // that exact call descriptor. We will link it in the CP cache exactly // as if it were an invokevirtual of MethodHandle.invoke. @@ -734,23 +730,30 @@ IRT_ENTRY(void, InterpreterRuntime::resolve_invokedynamic(JavaThread* thread)) { bytecode, info.resolved_method(), info.vtable_index()); - assert(pool->cache()->entry_at(main_index)->is_vfinal(), "f2 must be a methodOop"); } // The method (f2 entry) of the main entry is the MH.invoke for the // invokedynamic target call signature. - intptr_t f2_value = pool->cache()->entry_at(main_index)->f2(); - methodHandle signature_invoker(THREAD, (methodOop) f2_value); + oop f1_value = pool->cache()->entry_at(main_index)->f1(); + methodHandle signature_invoker(THREAD, (methodOop) f1_value); assert(signature_invoker.not_null() && signature_invoker->is_method() && signature_invoker->is_method_handle_invoke(), "correct result from LinkResolver::resolve_invokedynamic"); + Handle bootm = SystemDictionary::find_bootstrap_method(caller_method, caller_bci, + main_index, CHECK); + if (bootm.is_null()) { + THROW_MSG(vmSymbols::java_lang_IllegalStateException(), + "no bootstrap method found for invokedynamic"); + } + + // Short circuit if CallSite has been bound already: + if (!pool->cache()->secondary_entry_at(site_index)->is_f1_null()) + return; + symbolHandle call_site_name(THREAD, pool->name_ref_at(site_index)); Handle info; // NYI: Other metadata from a new kind of CP entry. (Annotations?) - // this is the index which gets stored on the CallSite object (as "callerPosition"): - int call_site_position = constantPoolCacheOopDesc::decode_secondary_index(site_index); - Handle call_site = SystemDictionary::make_dynamic_call_site(bootm, // Callee information: diff --git a/hotspot/src/share/vm/interpreter/linkResolver.cpp b/hotspot/src/share/vm/interpreter/linkResolver.cpp index 1c444a954ca..4a3669403f1 100644 --- a/hotspot/src/share/vm/interpreter/linkResolver.cpp +++ b/hotspot/src/share/vm/interpreter/linkResolver.cpp @@ -67,6 +67,15 @@ void CallInfo::set_virtual(KlassHandle resolved_klass, KlassHandle selected_klas set_common(resolved_klass, selected_klass, resolved_method, selected_method, vtable_index, CHECK); } +void CallInfo::set_dynamic(methodHandle resolved_method, TRAPS) { + assert(resolved_method->is_method_handle_invoke(), ""); + KlassHandle resolved_klass = SystemDictionaryHandles::MethodHandle_klass(); + assert(resolved_klass == resolved_method->method_holder(), ""); + int vtable_index = methodOopDesc::nonvirtual_vtable_index; + assert(resolved_method->vtable_index() == vtable_index, ""); + set_common(resolved_klass, KlassHandle(), resolved_method, resolved_method, vtable_index, CHECK); +} + void CallInfo::set_common(KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method, int vtable_index, TRAPS) { assert(resolved_method->signature() == selected_method->signature(), "signatures must correspond"); _resolved_klass = resolved_klass; @@ -176,9 +185,20 @@ void LinkResolver::lookup_implicit_method(methodHandle& result, KlassHandle klass, symbolHandle name, symbolHandle signature, KlassHandle current_klass, TRAPS) { - if (EnableMethodHandles && MethodHandles::enabled() && + if (EnableMethodHandles && klass() == SystemDictionary::MethodHandle_klass() && methodOopDesc::is_method_handle_invoke_name(name())) { + if (!MethodHandles::enabled()) { + // Make sure the Java part of the runtime has been booted up. + klassOop natives = SystemDictionary::MethodHandleNatives_klass(); + if (natives == NULL || instanceKlass::cast(natives)->is_not_initialized()) { + SystemDictionary::resolve_or_fail(vmSymbolHandles::sun_dyn_MethodHandleNatives(), + Handle(), + Handle(), + true, + CHECK); + } + } methodOop result_oop = SystemDictionary::find_method_handle_invoke(name, signature, current_klass, @@ -1065,7 +1085,7 @@ void LinkResolver::resolve_invokedynamic(CallInfo& result, constantPoolHandle po if (resolved_method.is_null()) { THROW(vmSymbols::java_lang_InternalError()); } - result.set_virtual(resolved_klass, KlassHandle(), resolved_method, resolved_method, resolved_method->vtable_index(), CHECK); + result.set_dynamic(resolved_method, CHECK); } //------------------------------------------------------------------------------------------------------------------------ diff --git a/hotspot/src/share/vm/interpreter/linkResolver.hpp b/hotspot/src/share/vm/interpreter/linkResolver.hpp index c39ea8f41db..f98db15a441 100644 --- a/hotspot/src/share/vm/interpreter/linkResolver.hpp +++ b/hotspot/src/share/vm/interpreter/linkResolver.hpp @@ -73,6 +73,7 @@ class CallInfo: public LinkInfo { void set_static( KlassHandle resolved_klass, methodHandle resolved_method , TRAPS); void set_interface(KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method , TRAPS); void set_virtual( KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method, int vtable_index, TRAPS); + void set_dynamic( methodHandle resolved_method, TRAPS); void set_common( KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method, int vtable_index, TRAPS); friend class LinkResolver; diff --git a/hotspot/src/share/vm/interpreter/rewriter.cpp b/hotspot/src/share/vm/interpreter/rewriter.cpp index 00afdf63a14..558e3138be5 100644 --- a/hotspot/src/share/vm/interpreter/rewriter.cpp +++ b/hotspot/src/share/vm/interpreter/rewriter.cpp @@ -32,14 +32,17 @@ void Rewriter::compute_index_maps() { const int length = _pool->length(); init_cp_map(length); + jint tag_mask = 0; for (int i = 0; i < length; i++) { int tag = _pool->tag_at(i).value(); + tag_mask |= (1 << tag); switch (tag) { case JVM_CONSTANT_InterfaceMethodref: case JVM_CONSTANT_Fieldref : // fall through case JVM_CONSTANT_Methodref : // fall through case JVM_CONSTANT_MethodHandle : // fall through case JVM_CONSTANT_MethodType : // fall through + case JVM_CONSTANT_InvokeDynamic : // fall through add_cp_cache_entry(i); break; } @@ -47,6 +50,8 @@ void Rewriter::compute_index_maps() { guarantee((int)_cp_cache_map.length()-1 <= (int)((u2)-1), "all cp cache indexes fit in a u2"); + + _have_invoke_dynamic = ((tag_mask & (1 << JVM_CONSTANT_InvokeDynamic)) != 0); } @@ -59,6 +64,28 @@ void Rewriter::make_constant_pool_cache(TRAPS) { constantPoolCacheOop cache = oopFactory::new_constantPoolCache(length, methodOopDesc::IsUnsafeConc, CHECK); cache->initialize(_cp_cache_map); + + // Don't bother to the next pass if there is no JVM_CONSTANT_InvokeDynamic. + if (_have_invoke_dynamic) { + for (int i = 0; i < length; i++) { + int pool_index = cp_cache_entry_pool_index(i); + if (pool_index >= 0 && + _pool->tag_at(pool_index).is_invoke_dynamic()) { + int bsm_index = _pool->invoke_dynamic_bootstrap_method_ref_index_at(pool_index); + if (bsm_index != 0) { + assert(_pool->tag_at(bsm_index).is_method_handle(), "must be a MH constant"); + // There is a CP cache entry holding the BSM for these calls. + int bsm_cache_index = cp_entry_to_cp_cache(bsm_index); + cache->entry_at(i)->initialize_bootstrap_method_index_in_cache(bsm_cache_index); + } else { + // There is no CP cache entry holding the BSM for these calls. + // We will need to look for a class-global BSM, later. + guarantee(AllowTransitionalJSR292, ""); + } + } + } + } + _pool->set_cache(cache); cache->set_constant_pool(_pool()); } diff --git a/hotspot/src/share/vm/interpreter/rewriter.hpp b/hotspot/src/share/vm/interpreter/rewriter.hpp index 91ad08a2b95..1f772a640a2 100644 --- a/hotspot/src/share/vm/interpreter/rewriter.hpp +++ b/hotspot/src/share/vm/interpreter/rewriter.hpp @@ -32,6 +32,7 @@ class Rewriter: public StackObj { objArrayHandle _methods; intArray _cp_map; intStack _cp_cache_map; + bool _have_invoke_dynamic; void init_cp_map(int length) { _cp_map.initialize(length, -1); @@ -56,6 +57,22 @@ class Rewriter: public StackObj { return cache_index; } + // Access the contents of _cp_cache_map to determine CP cache layout. + int cp_cache_entry_pool_index(int cache_index) { + int cp_index = _cp_cache_map[cache_index]; + if ((cp_index & _secondary_entry_tag) != 0) + return -1; + else + return cp_index; + } + int cp_cache_secondary_entry_main_index(int cache_index) { + int cp_index = _cp_cache_map[cache_index]; + if ((cp_index & _secondary_entry_tag) == 0) + return -1; + else + return (cp_index - _secondary_entry_tag); + } + // All the work goes in here: Rewriter(instanceKlassHandle klass, constantPoolHandle cpool, objArrayHandle methods, TRAPS); diff --git a/hotspot/src/share/vm/oops/constantPoolKlass.cpp b/hotspot/src/share/vm/oops/constantPoolKlass.cpp index ab00023b60f..dd4cb287c4a 100644 --- a/hotspot/src/share/vm/oops/constantPoolKlass.cpp +++ b/hotspot/src/share/vm/oops/constantPoolKlass.cpp @@ -379,6 +379,10 @@ void constantPoolKlass::oop_print_on(oop obj, outputStream* st) { case JVM_CONSTANT_MethodType : st->print("signature_index=%d", cp->method_type_index_at(index)); break; + case JVM_CONSTANT_InvokeDynamic : + st->print("bootstrap_method_index=%d", cp->invoke_dynamic_bootstrap_method_ref_index_at(index)); + st->print(" name_and_type_index=%d", cp->invoke_dynamic_name_and_type_ref_index_at(index)); + break; default: ShouldNotReachHere(); break; diff --git a/hotspot/src/share/vm/oops/constantPoolOop.cpp b/hotspot/src/share/vm/oops/constantPoolOop.cpp index 4915a4543dd..62e2f64dc79 100644 --- a/hotspot/src/share/vm/oops/constantPoolOop.cpp +++ b/hotspot/src/share/vm/oops/constantPoolOop.cpp @@ -264,10 +264,15 @@ symbolOop constantPoolOopDesc::impl_signature_ref_at(int which, bool uncached) { int constantPoolOopDesc::impl_name_and_type_ref_index_at(int which, bool uncached) { int i = which; if (!uncached && cache() != NULL) { - if (constantPoolCacheOopDesc::is_secondary_index(which)) + if (constantPoolCacheOopDesc::is_secondary_index(which)) { // Invokedynamic indexes are always processed in native order // so there is no question of reading a native u2 in Java order here. - return cache()->main_entry_at(which)->constant_pool_index(); + int pool_index = cache()->main_entry_at(which)->constant_pool_index(); + if (tag_at(pool_index).is_invoke_dynamic()) + pool_index = invoke_dynamic_name_and_type_ref_index_at(pool_index); + assert(tag_at(pool_index).is_name_and_type(), ""); + return pool_index; + } // change byte-ordering and go via cache i = remap_instruction_operand_from_cache(which); } else { @@ -830,6 +835,19 @@ bool constantPoolOopDesc::compare_entry_to(int index1, constantPoolHandle cp2, } } break; + case JVM_CONSTANT_InvokeDynamic: + { + int k1 = invoke_dynamic_bootstrap_method_ref_index_at(index1); + int k2 = cp2->invoke_dynamic_bootstrap_method_ref_index_at(index2); + if (k1 == k2) { + int i1 = invoke_dynamic_name_and_type_ref_index_at(index1); + int i2 = cp2->invoke_dynamic_name_and_type_ref_index_at(index2); + if (i1 == i2) { + return true; + } + } + } break; + case JVM_CONSTANT_UnresolvedString: { symbolOop s1 = unresolved_string_at(index1); @@ -1016,6 +1034,13 @@ void constantPoolOopDesc::copy_entry_to(int from_i, constantPoolHandle to_cp, to_cp->method_handle_index_at_put(to_i, k1, k2); } break; + case JVM_CONSTANT_InvokeDynamic: + { + int k1 = invoke_dynamic_bootstrap_method_ref_index_at(from_i); + int k2 = invoke_dynamic_name_and_type_ref_index_at(from_i); + to_cp->invoke_dynamic_at_put(to_i, k1, k2); + } break; + // Invalid is used as the tag for the second constant pool entry // occupied by JVM_CONSTANT_Double or JVM_CONSTANT_Long. It should // not be seen by itself. @@ -1231,6 +1256,7 @@ jint constantPoolOopDesc::cpool_entry_size(jint idx) { case JVM_CONSTANT_Methodref: case JVM_CONSTANT_InterfaceMethodref: case JVM_CONSTANT_NameAndType: + case JVM_CONSTANT_InvokeDynamic: return 5; case JVM_CONSTANT_Long: @@ -1444,6 +1470,15 @@ int constantPoolOopDesc::copy_cpool_bytes(int cpool_size, DBG(printf("JVM_CONSTANT_MethodType: %hd", idx1)); break; } + case JVM_CONSTANT_InvokeDynamic: { + *bytes = JVM_CONSTANT_InvokeDynamic; + idx1 = invoke_dynamic_bootstrap_method_ref_index_at(idx); + idx2 = invoke_dynamic_name_and_type_ref_index_at(idx); + Bytes::put_Java_u2((address) (bytes+1), idx1); + Bytes::put_Java_u2((address) (bytes+3), idx2); + DBG(printf("JVM_CONSTANT_InvokeDynamic: %hd %hd", idx1, idx2)); + break; + } } DBG(printf("\n")); bytes += ent_size; diff --git a/hotspot/src/share/vm/oops/constantPoolOop.hpp b/hotspot/src/share/vm/oops/constantPoolOop.hpp index 3ea9087636d..8b5889b45ee 100644 --- a/hotspot/src/share/vm/oops/constantPoolOop.hpp +++ b/hotspot/src/share/vm/oops/constantPoolOop.hpp @@ -156,6 +156,11 @@ class constantPoolOopDesc : public oopDesc { *int_at_addr(which) = ref_index; } + void invoke_dynamic_at_put(int which, int bootstrap_method_index, int name_and_type_index) { + tag_at_put(which, JVM_CONSTANT_InvokeDynamic); + *int_at_addr(which) = ((jint) name_and_type_index<<16) | bootstrap_method_index; + } + // Temporary until actual use void unresolved_string_at_put(int which, symbolOop s) { *obj_at_addr(which) = NULL; @@ -396,6 +401,16 @@ class constantPoolOopDesc : public oopDesc { int sym = method_type_index_at(which); return symbol_at(sym); } + int invoke_dynamic_bootstrap_method_ref_index_at(int which) { + assert(tag_at(which).is_invoke_dynamic(), "Corrupted constant pool"); + jint ref_index = *int_at_addr(which); + return extract_low_short_from_int(ref_index); + } + int invoke_dynamic_name_and_type_ref_index_at(int which) { + assert(tag_at(which).is_invoke_dynamic(), "Corrupted constant pool"); + jint ref_index = *int_at_addr(which); + return extract_high_short_from_int(ref_index); + } // The following methods (name/signature/klass_ref_at, klass_ref_at_noresolve, // name_and_type_ref_index_at) all expect to be passed indices obtained diff --git a/hotspot/src/share/vm/oops/cpCacheOop.cpp b/hotspot/src/share/vm/oops/cpCacheOop.cpp index f9533c5bd79..8542cf5eaa5 100644 --- a/hotspot/src/share/vm/oops/cpCacheOop.cpp +++ b/hotspot/src/share/vm/oops/cpCacheOop.cpp @@ -134,7 +134,7 @@ int ConstantPoolCacheEntry::field_index() const { void ConstantPoolCacheEntry::set_method(Bytecodes::Code invoke_code, methodHandle method, int vtable_index) { - + assert(!is_secondary_entry(), ""); assert(method->interpreter_entry() != NULL, "should have been set at this point"); assert(!method->is_obsolete(), "attempt to write obsolete method to cpCache"); bool change_to_virtual = (invoke_code == Bytecodes::_invokeinterface); @@ -142,7 +142,6 @@ void ConstantPoolCacheEntry::set_method(Bytecodes::Code invoke_code, int byte_no = -1; bool needs_vfinal_flag = false; switch (invoke_code) { - case Bytecodes::_invokedynamic: case Bytecodes::_invokevirtual: case Bytecodes::_invokeinterface: { if (method->can_be_statically_bound()) { @@ -155,6 +154,23 @@ void ConstantPoolCacheEntry::set_method(Bytecodes::Code invoke_code, byte_no = 2; break; } + + case Bytecodes::_invokedynamic: // similar to _invokevirtual + if (TraceInvokeDynamic) { + tty->print_cr("InvokeDynamic set_method%s method="PTR_FORMAT" index=%d", + (is_secondary_entry() ? " secondary" : ""), + (intptr_t)method(), vtable_index); + method->print(); + this->print(tty, 0); + } + assert(method->can_be_statically_bound(), "must be a MH invoker method"); + assert(AllowTransitionalJSR292 || _f2 >= constantPoolOopDesc::CPCACHE_INDEX_TAG, "BSM index initialized"); + set_f1(method()); + needs_vfinal_flag = false; // _f2 is not an oop + assert(!is_vfinal(), "f2 not an oop"); + byte_no = 1; // just a formality + break; + case Bytecodes::_invokespecial: // Preserve the value of the vfinal flag on invokevirtual bytecode // which may be shared with this constant pool cache entry. @@ -209,6 +225,7 @@ void ConstantPoolCacheEntry::set_method(Bytecodes::Code invoke_code, void ConstantPoolCacheEntry::set_interface_call(methodHandle method, int index) { + assert(!is_secondary_entry(), ""); klassOop interf = method->method_holder(); assert(instanceKlass::cast(interf)->is_interface(), "must be an interface"); set_f1(interf); @@ -218,8 +235,23 @@ void ConstantPoolCacheEntry::set_interface_call(methodHandle method, int index) } +void ConstantPoolCacheEntry::initialize_bootstrap_method_index_in_cache(int bsm_cache_index) { + assert(!is_secondary_entry(), "only for JVM_CONSTANT_InvokeDynamic main entry"); + assert(_f2 == 0, "initialize once"); + assert(bsm_cache_index == (int)(u2)bsm_cache_index, "oob"); + set_f2(bsm_cache_index + constantPoolOopDesc::CPCACHE_INDEX_TAG); +} + +int ConstantPoolCacheEntry::bootstrap_method_index_in_cache() { + assert(!is_secondary_entry(), "only for JVM_CONSTANT_InvokeDynamic main entry"); + intptr_t bsm_cache_index = (intptr_t) _f2 - constantPoolOopDesc::CPCACHE_INDEX_TAG; + assert(bsm_cache_index == (intptr_t)(u2)bsm_cache_index, "oob"); + return (int) bsm_cache_index; +} + void ConstantPoolCacheEntry::set_dynamic_call(Handle call_site, methodHandle signature_invoker) { + assert(is_secondary_entry(), ""); int param_size = signature_invoker->size_of_parameters(); assert(param_size >= 1, "method argument size must include MH.this"); param_size -= 1; // do not count MH.this; it is not stacked for invokedynamic @@ -227,7 +259,6 @@ void ConstantPoolCacheEntry::set_dynamic_call(Handle call_site, // racing threads might be trying to install their own favorites set_f1(call_site()); } - //set_f2(0); bool is_final = true; assert(signature_invoker->is_final_method(), "is_final"); set_flags(as_flags(as_TosState(signature_invoker->result_type()), is_final, false, false, false, true) | param_size); @@ -417,14 +448,14 @@ void ConstantPoolCacheEntry::print(outputStream* st, int index) const { // print separator if (index == 0) tty->print_cr(" -------------"); // print entry - tty->print_cr("%3d (%08x) ", index, this); + tty->print("%3d ("PTR_FORMAT") ", index, (intptr_t)this); if (is_secondary_entry()) tty->print_cr("[%5d|secondary]", main_entry_index()); else tty->print_cr("[%02x|%02x|%5d]", bytecode_2(), bytecode_1(), constant_pool_index()); - tty->print_cr(" [ %08x]", (address)(oop)_f1); - tty->print_cr(" [ %08x]", _f2); - tty->print_cr(" [ %08x]", _flags); + tty->print_cr(" [ "PTR_FORMAT"]", (intptr_t)(oop)_f1); + tty->print_cr(" [ "PTR_FORMAT"]", (intptr_t)_f2); + tty->print_cr(" [ "PTR_FORMAT"]", (intptr_t)_flags); tty->print_cr(" -------------"); } diff --git a/hotspot/src/share/vm/oops/cpCacheOop.hpp b/hotspot/src/share/vm/oops/cpCacheOop.hpp index 0759815697c..4253413b06d 100644 --- a/hotspot/src/share/vm/oops/cpCacheOop.hpp +++ b/hotspot/src/share/vm/oops/cpCacheOop.hpp @@ -185,6 +185,10 @@ class ConstantPoolCacheEntry VALUE_OBJ_CLASS_SPEC { methodHandle signature_invoker // determines signature information ); + // For JVM_CONSTANT_InvokeDynamic cache entries: + void initialize_bootstrap_method_index_in_cache(int bsm_cache_index); + int bootstrap_method_index_in_cache(); + void set_parameter_size(int value) { assert(parameter_size() == 0 || parameter_size() == value, "size must not change"); @@ -234,6 +238,7 @@ class ConstantPoolCacheEntry VALUE_OBJ_CLASS_SPEC { Bytecodes::Code bytecode_1() const { return Bytecodes::cast((_indices >> 16) & 0xFF); } Bytecodes::Code bytecode_2() const { return Bytecodes::cast((_indices >> 24) & 0xFF); } volatile oop f1() const { return _f1; } + bool is_f1_null() const { return (oop)_f1 == NULL; } // classifies a CPC entry as unbound intx f2() const { return _f2; } int field_index() const; int parameter_size() const { return _flags & 0xFF; } diff --git a/hotspot/src/share/vm/prims/jvm.h b/hotspot/src/share/vm/prims/jvm.h index 1445a32d65a..bd982910111 100644 --- a/hotspot/src/share/vm/prims/jvm.h +++ b/hotspot/src/share/vm/prims/jvm.h @@ -1046,7 +1046,8 @@ enum { JVM_CONSTANT_InterfaceMethodref, JVM_CONSTANT_NameAndType, JVM_CONSTANT_MethodHandle = 15, // JSR 292 - JVM_CONSTANT_MethodType = 16 // JSR 292 + JVM_CONSTANT_MethodType = 16, // JSR 292 + JVM_CONSTANT_InvokeDynamic = 17 // JSR 292 }; /* JVM_CONSTANT_MethodHandle subtypes */ diff --git a/hotspot/src/share/vm/prims/methodHandles.cpp b/hotspot/src/share/vm/prims/methodHandles.cpp index f084b5af82f..7b3acfda1e1 100644 --- a/hotspot/src/share/vm/prims/methodHandles.cpp +++ b/hotspot/src/share/vm/prims/methodHandles.cpp @@ -2475,6 +2475,10 @@ JVM_END JVM_ENTRY(void, MHI_registerBootstrap(JNIEnv *env, jobject igcls, jclass caller_jh, jobject bsm_jh)) { instanceKlassHandle ik = MethodHandles::resolve_instance_klass(caller_jh, THREAD); + if (!AllowTransitionalJSR292) { + THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), + "registerBootstrapMethod is only supported in JSR 292 EDR"); + } ik->link_class(CHECK); if (!java_dyn_MethodHandle::is_instance(JNIHandles::resolve(bsm_jh))) { THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "method handle"); diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index d4f84c4450e..daf5b6b6ba5 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -3517,6 +3517,9 @@ class CommandLineFlags { experimental(bool, EnableInvokeDynamic, false, \ "recognize the invokedynamic instruction") \ \ + experimental(bool, AllowTransitionalJSR292, true, \ + "recognize pre-PFD formats of invokedynamic") \ + \ develop(bool, TraceInvokeDynamic, false, \ "trace internal invoke dynamic operations") \ \ diff --git a/hotspot/src/share/vm/utilities/constantTag.cpp b/hotspot/src/share/vm/utilities/constantTag.cpp index f6fb94a63c9..4d0bfe89bfb 100644 --- a/hotspot/src/share/vm/utilities/constantTag.cpp +++ b/hotspot/src/share/vm/utilities/constantTag.cpp @@ -91,6 +91,8 @@ const char* constantTag::internal_name() const { return "MethodHandle"; case JVM_CONSTANT_MethodType : return "MethodType"; + case JVM_CONSTANT_InvokeDynamic : + return "InvokeDynamic"; case JVM_CONSTANT_Object : return "Object"; case JVM_CONSTANT_Utf8 : diff --git a/hotspot/src/share/vm/utilities/constantTag.hpp b/hotspot/src/share/vm/utilities/constantTag.hpp index 97a9fe99104..39e335039e7 100644 --- a/hotspot/src/share/vm/utilities/constantTag.hpp +++ b/hotspot/src/share/vm/utilities/constantTag.hpp @@ -80,13 +80,14 @@ class constantTag VALUE_OBJ_CLASS_SPEC { bool is_method_type() const { return _tag == JVM_CONSTANT_MethodType; } bool is_method_handle() const { return _tag == JVM_CONSTANT_MethodHandle; } + bool is_invoke_dynamic() const { return _tag == JVM_CONSTANT_InvokeDynamic; } constantTag() { _tag = JVM_CONSTANT_Invalid; } constantTag(jbyte tag) { assert((tag >= 0 && tag <= JVM_CONSTANT_NameAndType) || - (tag >= JVM_CONSTANT_MethodHandle && tag <= JVM_CONSTANT_MethodType) || + (tag >= JVM_CONSTANT_MethodHandle && tag <= JVM_CONSTANT_InvokeDynamic) || (tag >= JVM_CONSTANT_InternalMin && tag <= JVM_CONSTANT_InternalMax), "Invalid constant tag"); _tag = tag; } From 98f8ed01aadc094d41f7f9d52946f8d4526e63f3 Mon Sep 17 00:00:00 2001 From: Xueming Shen Date: Fri, 16 Jul 2010 16:45:52 -0400 Subject: [PATCH 08/56] 6964313: Find sun/nio/cs/ext issue with CreateSymbols, then move sun/nio/cs/ext to charset.jar Removed the duplicate sun.nio.cs.ext entries from rt.jar and moved X11 charsets into charsets.jar Reviewed-by: ohair --- jdk/make/common/Release.gmk | 10 ++++++++++ jdk/make/sun/nio/cs/Makefile | 19 +++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/jdk/make/common/Release.gmk b/jdk/make/common/Release.gmk index cf16ea8dd3a..bc40dcc9725 100644 --- a/jdk/make/common/Release.gmk +++ b/jdk/make/common/Release.gmk @@ -571,6 +571,16 @@ $(NOT_RT_JAR_LIST): FRC $(ECHO) "META-INF/services/com.sun.tools.xjc.Plugin" >> $@ $(ECHO) "com/sun/tools/" >> $@ $(ECHO) "sun/jvmstat/" >> $@ + $(ECHO) "sun/nio/cs/ext/" >> $@ + $(ECHO) "sun/awt/HKSCS.class" >> $@ + $(ECHO) "sun/awt/motif/X11GB2312$Decoder.class" >> $@ + $(ECHO) "sun/awt/motif/X11GB2312$Encoder.class" >> $@ + $(ECHO) "sun/awt/motif/X11GB2312.class" >> $@ + $(ECHO) "sun/awt/motif/X11GBK$Encoder.class" >> $@ + $(ECHO) "sun/awt/motif/X11GBK.class" >> $@ + $(ECHO) "sun/awt/motif/X11KSC5601$Decoder.class" >> $@ + $(ECHO) "sun/awt/motif/X11KSC5601$Encoder.class" >> $@ + $(ECHO) "sun/awt/motif/X11KSC5601.class" >> $@ $(ECHO) "sun/rmi/rmic/" >> $@ $(ECHO) "sun/tools/asm/" >> $@ $(ECHO) "sun/tools/java/" >> $@ diff --git a/jdk/make/sun/nio/cs/Makefile b/jdk/make/sun/nio/cs/Makefile index 26437efca82..e1b4d8d7be5 100644 --- a/jdk/make/sun/nio/cs/Makefile +++ b/jdk/make/sun/nio/cs/Makefile @@ -57,6 +57,25 @@ CHARSETS_JAR = $(LIBDIR)/charsets.jar # extcs FILES_genout_extcs = $(FILES_gen_extcs:%.java=$(GENSRCDIR)/%.java) +# +# These sun.awt charsets use sun/nio/cs/ext charsets that only exist +# in JDK7 charsets.jar, which causes problem when build the symbol +# table for rt.jar in Release.gmk. They are now removed from the +# rt.jar when building jdk/jre image (in Release.gmk), so add them +# into charsets.jar here +# +ifeq ($(PLATFORM), windows) +FILES_src += \ + sun/awt/HKSCS.java +else +# Solaris/Linux +FILES_src += \ + sun/awt/HKSCS.java \ + sun/awt/motif/X11GB2312.java \ + sun/awt/motif/X11GBK.java \ + sun/awt/motif/X11KSC5601.java +endif # PLATFORM + # # Rules # From 7e34622217de977e79bb5b0c77a3a11da70960fe Mon Sep 17 00:00:00 2001 From: John R Rose Date: Fri, 16 Jul 2010 18:14:19 -0700 Subject: [PATCH 09/56] 6969574: invokedynamic call sites deoptimize instead of executing Reviewed-by: kvn --- hotspot/src/share/vm/ci/ciEnv.cpp | 4 ++-- hotspot/src/share/vm/ci/ciMethod.cpp | 23 ++++++------------- hotspot/src/share/vm/oops/cpCacheOop.cpp | 2 +- hotspot/src/share/vm/oops/cpCacheOop.hpp | 1 + hotspot/src/share/vm/oops/methodOop.cpp | 12 +++++++--- .../src/share/vm/prims/methodHandleWalk.cpp | 9 +++++++- 6 files changed, 28 insertions(+), 23 deletions(-) diff --git a/hotspot/src/share/vm/ci/ciEnv.cpp b/hotspot/src/share/vm/ci/ciEnv.cpp index a21d79a2352..de1fb564d76 100644 --- a/hotspot/src/share/vm/ci/ciEnv.cpp +++ b/hotspot/src/share/vm/ci/ciEnv.cpp @@ -728,8 +728,8 @@ ciMethod* ciEnv::get_fake_invokedynamic_method_impl(constantPoolHandle cpool, } // Get the invoker methodOop from the constant pool. - intptr_t f2_value = cpool->cache()->main_entry_at(index)->f2(); - methodOop signature_invoker = methodOop(f2_value); + oop f1_value = cpool->cache()->main_entry_at(index)->f1(); + methodOop signature_invoker = methodOop(f1_value); assert(signature_invoker != NULL && signature_invoker->is_method() && signature_invoker->is_method_handle_invoke(), "correct result from LinkResolver::resolve_invokedynamic"); diff --git a/hotspot/src/share/vm/ci/ciMethod.cpp b/hotspot/src/share/vm/ci/ciMethod.cpp index 22fc4f5fb78..f8c784f2ffe 100644 --- a/hotspot/src/share/vm/ci/ciMethod.cpp +++ b/hotspot/src/share/vm/ci/ciMethod.cpp @@ -694,30 +694,21 @@ int ciMethod::scale_count(int count, float prof_factor) { // ------------------------------------------------------------------ // ciMethod::is_method_handle_invoke // -// Return true if the method is a MethodHandle target. +// Return true if the method is an instance of one of the two +// signature-polymorphic MethodHandle methods, invokeExact or invokeGeneric. bool ciMethod::is_method_handle_invoke() const { - bool flag = (holder()->name() == ciSymbol::java_dyn_MethodHandle() && - methodOopDesc::is_method_handle_invoke_name(name()->sid())); -#ifdef ASSERT - if (is_loaded()) { - bool flag2 = ((flags().as_int() & JVM_MH_INVOKE_BITS) == JVM_MH_INVOKE_BITS); - { - VM_ENTRY_MARK; - bool flag3 = get_methodOop()->is_method_handle_invoke(); - assert(flag2 == flag3, "consistent"); - assert(flag == flag3, "consistent"); - } - } -#endif //ASSERT - return flag; + if (!is_loaded()) return false; + VM_ENTRY_MARK; + return get_methodOop()->is_method_handle_invoke(); } // ------------------------------------------------------------------ // ciMethod::is_method_handle_adapter // // Return true if the method is a generated MethodHandle adapter. +// These are built by MethodHandleCompiler. bool ciMethod::is_method_handle_adapter() const { - check_is_loaded(); + if (!is_loaded()) return false; VM_ENTRY_MARK; return get_methodOop()->is_method_handle_adapter(); } diff --git a/hotspot/src/share/vm/oops/cpCacheOop.cpp b/hotspot/src/share/vm/oops/cpCacheOop.cpp index 8542cf5eaa5..eb27f1658ab 100644 --- a/hotspot/src/share/vm/oops/cpCacheOop.cpp +++ b/hotspot/src/share/vm/oops/cpCacheOop.cpp @@ -168,7 +168,7 @@ void ConstantPoolCacheEntry::set_method(Bytecodes::Code invoke_code, set_f1(method()); needs_vfinal_flag = false; // _f2 is not an oop assert(!is_vfinal(), "f2 not an oop"); - byte_no = 1; // just a formality + byte_no = 1; // coordinate this with bytecode_number & is_resolved break; case Bytecodes::_invokespecial: diff --git a/hotspot/src/share/vm/oops/cpCacheOop.hpp b/hotspot/src/share/vm/oops/cpCacheOop.hpp index 4253413b06d..68460717fe0 100644 --- a/hotspot/src/share/vm/oops/cpCacheOop.hpp +++ b/hotspot/src/share/vm/oops/cpCacheOop.hpp @@ -211,6 +211,7 @@ class ConstantPoolCacheEntry VALUE_OBJ_CLASS_SPEC { case Bytecodes::_getfield : // fall through case Bytecodes::_invokespecial : // fall through case Bytecodes::_invokestatic : // fall through + case Bytecodes::_invokedynamic : // fall through case Bytecodes::_invokeinterface : return 1; case Bytecodes::_putstatic : // fall through case Bytecodes::_putfield : // fall through diff --git a/hotspot/src/share/vm/oops/methodOop.cpp b/hotspot/src/share/vm/oops/methodOop.cpp index 75a9d23dc72..ec32108d2a6 100644 --- a/hotspot/src/share/vm/oops/methodOop.cpp +++ b/hotspot/src/share/vm/oops/methodOop.cpp @@ -851,9 +851,15 @@ jint* methodOopDesc::method_type_offsets_chain() { // MethodHandleCompiler. // Must be consistent with MethodHandleCompiler::get_method_oop(). bool methodOopDesc::is_method_handle_adapter() const { - return (is_method_handle_invoke_name(name()) && - is_synthetic() && - MethodHandleCompiler::klass_is_method_handle_adapter_holder(method_holder())); + if (is_synthetic() && + !is_native() && // has code from MethodHandleCompiler + is_method_handle_invoke_name(name()) && + MethodHandleCompiler::klass_is_method_handle_adapter_holder(method_holder())) { + assert(!is_method_handle_invoke(), "disjoint"); + return true; + } else { + return false; + } } methodHandle methodOopDesc::make_invoke_method(KlassHandle holder, diff --git a/hotspot/src/share/vm/prims/methodHandleWalk.cpp b/hotspot/src/share/vm/prims/methodHandleWalk.cpp index f41f63a16a0..6a82f4b2436 100644 --- a/hotspot/src/share/vm/prims/methodHandleWalk.cpp +++ b/hotspot/src/share/vm/prims/methodHandleWalk.cpp @@ -738,6 +738,12 @@ void MethodHandleCompiler::emit_bc(Bytecodes::Code op, int index) { // bi case Bytecodes::_ldc: + assert(Bytecodes::format_bits(op, false) == (Bytecodes::_fmt_b|Bytecodes::_fmt_has_k), "wrong bytecode format"); + assert((char) index == index, "index does not fit in 8-bit"); + _bytecode.push(op); + _bytecode.push(index); + break; + case Bytecodes::_iload: case Bytecodes::_lload: case Bytecodes::_fload: @@ -754,7 +760,8 @@ void MethodHandleCompiler::emit_bc(Bytecodes::Code op, int index) { _bytecode.push(index); break; - // bii + // bkk + case Bytecodes::_ldc_w: case Bytecodes::_ldc2_w: case Bytecodes::_checkcast: assert(Bytecodes::format_bits(op, false) == Bytecodes::_fmt_bkk, "wrong bytecode format"); From daf491a814c75a35085a2f55915daac25c6438a3 Mon Sep 17 00:00:00 2001 From: John Coomes Date: Fri, 16 Jul 2010 21:33:21 -0700 Subject: [PATCH 10/56] 6962947: shared TaskQueue statistics Reviewed-by: tonyp, ysr --- .../concurrentMarkSweepGeneration.cpp | 13 +-- .../parNew/parNewGeneration.cpp | 7 +- .../parNew/parNewGeneration.hpp | 12 +-- .../parNew/parOopClosures.hpp | 5 +- .../parallelScavenge/psPromotionManager.cpp | 92 +++++++++---------- .../parallelScavenge/psPromotionManager.hpp | 65 +++---------- .../psPromotionManager.inline.hpp | 10 +- .../parallelScavenge/psTasks.cpp | 9 +- .../share/vm/utilities/globalDefinitions.hpp | 31 ++++++- hotspot/src/share/vm/utilities/taskqueue.cpp | 42 +++++++++ hotspot/src/share/vm/utilities/taskqueue.hpp | 87 +++++++++++++++++- 11 files changed, 236 insertions(+), 137 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp index 0aa08ec3018..1fac91a5466 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp @@ -664,19 +664,14 @@ CMSCollector::CMSCollector(ConcurrentMarkSweepGeneration* cmsGen, return; } - // XXX use a global constant instead of 64! - typedef struct OopTaskQueuePadded { - OopTaskQueue work_queue; - char pad[64 - sizeof(OopTaskQueue)]; // prevent false sharing - } OopTaskQueuePadded; - + typedef Padded PaddedOopTaskQueue; for (i = 0; i < num_queues; i++) { - OopTaskQueuePadded *q_padded = new OopTaskQueuePadded(); - if (q_padded == NULL) { + PaddedOopTaskQueue *q = new PaddedOopTaskQueue(); + if (q == NULL) { warning("work_queue allocation failure."); return; } - _task_queues->register_queue(i, &q_padded->work_queue); + _task_queues->register_queue(i, q); } for (i = 0; i < num_queues; i++) { _task_queues->queue(i)->initialize(); diff --git a/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp index 250d244d25a..dc655aed136 100644 --- a/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp +++ b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp @@ -539,10 +539,9 @@ ParNewGeneration(ReservedSpace rs, size_t initial_byte_size, int level) guarantee(_task_queues != NULL, "task_queues allocation failure."); for (uint i1 = 0; i1 < ParallelGCThreads; i1++) { - ObjToScanQueuePadded *q_padded = new ObjToScanQueuePadded(); - guarantee(q_padded != NULL, "work_queue Allocation failure."); - - _task_queues->register_queue(i1, &q_padded->work_queue); + ObjToScanQueue *q = new ObjToScanQueue(); + guarantee(q != NULL, "work_queue Allocation failure."); + _task_queues->register_queue(i1, q); } for (uint i2 = 0; i2 < ParallelGCThreads; i2++) diff --git a/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.hpp b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.hpp index afbab7b99c5..8196e621372 100644 --- a/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.hpp +++ b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,8 +33,8 @@ class ParEvacuateFollowersClosure; // but they must be here to allow ParScanClosure::do_oop_work to be defined // in genOopClosures.inline.hpp. -typedef OopTaskQueue ObjToScanQueue; -typedef OopTaskQueueSet ObjToScanQueueSet; +typedef Padded ObjToScanQueue; +typedef GenericTaskQueueSet ObjToScanQueueSet; // Enable this to get push/pop/steal stats. const int PAR_STATS_ENABLED = 0; @@ -304,12 +304,6 @@ class ParNewGeneration: public DefNewGeneration { friend class ParEvacuateFollowersClosure; private: - // XXX use a global constant instead of 64! - struct ObjToScanQueuePadded { - ObjToScanQueue work_queue; - char pad[64 - sizeof(ObjToScanQueue)]; // prevent false sharing - }; - // The per-worker-thread work queues ObjToScanQueueSet* _task_queues; diff --git a/hotspot/src/share/vm/gc_implementation/parNew/parOopClosures.hpp b/hotspot/src/share/vm/gc_implementation/parNew/parOopClosures.hpp index f261f31b752..c6a2543d0f5 100644 --- a/hotspot/src/share/vm/gc_implementation/parNew/parOopClosures.hpp +++ b/hotspot/src/share/vm/gc_implementation/parNew/parOopClosures.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,8 @@ class ParScanThreadState; class ParNewGeneration; -typedef OopTaskQueueSet ObjToScanQueueSet; +typedef Padded ObjToScanQueue; +typedef GenericTaskQueueSet ObjToScanQueueSet; class ParallelTaskTerminator; class ParScanClosure: public OopsInGenClosure { diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.cpp index 8453ce9185e..2da32555dee 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.cpp @@ -90,10 +90,7 @@ void PSPromotionManager::pre_scavenge() { } void PSPromotionManager::post_scavenge() { -#if PS_PM_STATS - print_stats(); -#endif // PS_PM_STATS - + TASKQUEUE_STATS_ONLY(if (PrintGCDetails && ParallelGCVerbose) print_stats()); for (uint i = 0; i < ParallelGCThreads + 1; i++) { PSPromotionManager* manager = manager_array(i); if (UseDepthFirstScavengeOrder) { @@ -105,37 +102,58 @@ void PSPromotionManager::post_scavenge() { } } -#if PS_PM_STATS +#if TASKQUEUE_STATS +void +PSPromotionManager::print_taskqueue_stats(uint i) const { + const TaskQueueStats& stats = depth_first() ? + _claimed_stack_depth.stats : _claimed_stack_breadth.stats; + tty->print("%3u ", i); + stats.print(); + tty->cr(); +} void -PSPromotionManager::print_stats(uint i) { - tty->print_cr("---- GC Worker %2d Stats", i); - tty->print_cr(" total pushes %8d", _total_pushes); - tty->print_cr(" masked pushes %8d", _masked_pushes); - tty->print_cr(" overflow pushes %8d", _overflow_pushes); - tty->print_cr(" max overflow length %8d", _max_overflow_length); - tty->print_cr(""); - tty->print_cr(" arrays chunked %8d", _arrays_chunked); - tty->print_cr(" array chunks processed %8d", _array_chunks_processed); - tty->print_cr(""); - tty->print_cr(" total steals %8d", _total_steals); - tty->print_cr(" masked steals %8d", _masked_steals); - tty->print_cr(""); +PSPromotionManager::print_local_stats(uint i) const { + #define FMT " " SIZE_FORMAT_W(10) + tty->print_cr("%3u" FMT FMT FMT FMT, i, _masked_pushes, _masked_steals, + _arrays_chunked, _array_chunks_processed); + #undef FMT } +static const char* const pm_stats_hdr[] = { + " --------masked------- arrays array", + "thr push steal chunked chunks", + "--- ---------- ---------- ---------- ----------" +}; + void PSPromotionManager::print_stats() { - tty->print_cr("== GC Tasks Stats (%s), GC %3d", - (UseDepthFirstScavengeOrder) ? "Depth-First" : "Breadth-First", + const bool df = UseDepthFirstScavengeOrder; + tty->print_cr("== GC Task Stats (%s-First), GC %3d", df ? "Depth" : "Breadth", Universe::heap()->total_collections()); - for (uint i = 0; i < ParallelGCThreads+1; ++i) { - PSPromotionManager* manager = manager_array(i); - manager->print_stats(i); + tty->print("thr "); TaskQueueStats::print_header(1); tty->cr(); + tty->print("--- "); TaskQueueStats::print_header(2); tty->cr(); + for (uint i = 0; i < ParallelGCThreads + 1; ++i) { + manager_array(i)->print_taskqueue_stats(i); + } + + const uint hlines = sizeof(pm_stats_hdr) / sizeof(pm_stats_hdr[0]); + for (uint i = 0; i < hlines; ++i) tty->print_cr(pm_stats_hdr[i]); + for (uint i = 0; i < ParallelGCThreads + 1; ++i) { + manager_array(i)->print_local_stats(i); } } -#endif // PS_PM_STATS +void +PSPromotionManager::reset_stats() { + TaskQueueStats& stats = depth_first() ? + claimed_stack_depth()->stats : claimed_stack_breadth()->stats; + stats.reset(); + _masked_pushes = _masked_steals = 0; + _arrays_chunked = _array_chunks_processed = 0; +} +#endif // TASKQUEUE_STATS PSPromotionManager::PSPromotionManager() { ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap(); @@ -189,16 +207,7 @@ void PSPromotionManager::reset() { _prefetch_queue.clear(); -#if PS_PM_STATS - _total_pushes = 0; - _masked_pushes = 0; - _overflow_pushes = 0; - _max_overflow_length = 0; - _arrays_chunked = 0; - _array_chunks_processed = 0; - _total_steals = 0; - _masked_steals = 0; -#endif // PS_PM_STATS + TASKQUEUE_STATS_ONLY(reset_stats()); } @@ -423,14 +432,9 @@ oop PSPromotionManager::copy_to_survivor_space(oop o, bool depth_first) { new_obj->is_objArray() && PSChunkLargeArrays) { // we'll chunk it -#if PS_PM_STATS - ++_arrays_chunked; -#endif // PS_PM_STATS oop* const masked_o = mask_chunked_array_oop(o); push_depth(masked_o); -#if PS_PM_STATS - ++_masked_pushes; -#endif // PS_PM_STATS + TASKQUEUE_STATS_ONLY(++_arrays_chunked; ++_masked_pushes); } else { // we'll just push its contents new_obj->push_contents(this); @@ -494,9 +498,7 @@ void PSPromotionManager::process_array_chunk(oop old) { assert(old->is_objArray(), "invariant"); assert(old->is_forwarded(), "invariant"); -#if PS_PM_STATS - ++_array_chunks_processed; -#endif // PS_PM_STATS + TASKQUEUE_STATS_ONLY(++_array_chunks_processed); oop const obj = old->forwardee(); @@ -508,9 +510,7 @@ void PSPromotionManager::process_array_chunk(oop old) { assert(start > 0, "invariant"); arrayOop(old)->set_length(start); push_depth(mask_chunked_array_oop(old)); -#if PS_PM_STATS - ++_masked_pushes; -#endif // PS_PM_STATS + TASKQUEUE_STATS_ONLY(++_masked_pushes); } else { // this is the final chunk for this array start = 0; diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.hpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.hpp index 07694fc94ce..ec89b9557bb 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.hpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.hpp @@ -42,8 +42,6 @@ class MutableSpace; class PSOldGen; class ParCompactionManager; -#define PS_PM_STATS 0 - class PSPromotionManager : public CHeapObj { friend class PSScavenge; friend class PSRefProcTaskExecutor; @@ -54,22 +52,18 @@ class PSPromotionManager : public CHeapObj { static PSOldGen* _old_gen; static MutableSpace* _young_space; -#if PS_PM_STATS - uint _total_pushes; - uint _masked_pushes; +#if TASKQUEUE_STATS + size_t _masked_pushes; + size_t _masked_steals; + size_t _arrays_chunked; + size_t _array_chunks_processed; - uint _overflow_pushes; - uint _max_overflow_length; - - uint _arrays_chunked; - uint _array_chunks_processed; - - uint _total_steals; - uint _masked_steals; - - void print_stats(uint i); + void print_taskqueue_stats(uint i) const; + void print_local_stats(uint i) const; static void print_stats(); -#endif // PS_PM_STATS + + void reset_stats(); +#endif // TASKQUEUE_STATS PSYoungPromotionLAB _young_lab; PSOldPromotionLAB _old_lab; @@ -143,42 +137,12 @@ class PSPromotionManager : public CHeapObj { template void push_depth(T* p) { assert(depth_first(), "pre-condition"); - -#if PS_PM_STATS - ++_total_pushes; - int stack_length = claimed_stack_depth()->overflow_stack()->length(); -#endif // PS_PM_STATS - claimed_stack_depth()->push(p); - -#if PS_PM_STATS - if (claimed_stack_depth()->overflow_stack()->length() != stack_length) { - ++_overflow_pushes; - if ((uint)stack_length + 1 > _max_overflow_length) { - _max_overflow_length = (uint)stack_length + 1; - } - } -#endif // PS_PM_STATS } void push_breadth(oop o) { assert(!depth_first(), "pre-condition"); - -#if PS_PM_STATS - ++_total_pushes; - int stack_length = claimed_stack_breadth()->overflow_stack()->length(); -#endif // PS_PM_STATS - claimed_stack_breadth()->push(o); - -#if PS_PM_STATS - if (claimed_stack_breadth()->overflow_stack()->length() != stack_length) { - ++_overflow_pushes; - if ((uint)stack_length + 1 > _max_overflow_length) { - _max_overflow_length = (uint)stack_length + 1; - } - } -#endif // PS_PM_STATS } protected: @@ -256,12 +220,5 @@ class PSPromotionManager : public CHeapObj { template inline void claim_or_forward_depth(T* p); template inline void claim_or_forward_breadth(T* p); -#if PS_PM_STATS - void increment_steals(oop* p = NULL) { - _total_steals += 1; - if (p != NULL && is_oop_masked(p)) { - _masked_steals += 1; - } - } -#endif // PS_PM_STATS + TASKQUEUE_STATS_ONLY(inline void record_steal(StarTask& p);) }; diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.inline.hpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.inline.hpp index 213f6261401..ea81c817b30 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.inline.hpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -124,3 +124,11 @@ inline void PSPromotionManager::process_popped_location_depth(StarTask p) { } } } + +#if TASKQUEUE_STATS +void PSPromotionManager::record_steal(StarTask& p) { + if (is_oop_masked(p)) { + ++_masked_steals; + } +} +#endif // TASKQUEUE_STATS diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psTasks.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psTasks.cpp index bbff68c6b2c..6f72724bfda 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psTasks.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psTasks.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -148,9 +148,7 @@ void StealTask::do_it(GCTaskManager* manager, uint which) { while(true) { StarTask p; if (PSPromotionManager::steal_depth(which, &random_seed, p)) { -#if PS_PM_STATS - pm->increment_steals(p); -#endif // PS_PM_STATS + TASKQUEUE_STATS_ONLY(pm->record_steal(p)); pm->process_popped_location_depth(p); pm->drain_stacks_depth(true); } else { @@ -163,9 +161,6 @@ void StealTask::do_it(GCTaskManager* manager, uint which) { while(true) { oop obj; if (PSPromotionManager::steal_breadth(which, &random_seed, obj)) { -#if PS_PM_STATS - pm->increment_steals(); -#endif // PS_PM_STATS obj->copy_contents(pm); pm->drain_stacks_breadth(true); } else { diff --git a/hotspot/src/share/vm/utilities/globalDefinitions.hpp b/hotspot/src/share/vm/utilities/globalDefinitions.hpp index a5a8ae403d2..97d96c21f12 100644 --- a/hotspot/src/share/vm/utilities/globalDefinitions.hpp +++ b/hotspot/src/share/vm/utilities/globalDefinitions.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -345,6 +345,35 @@ inline intptr_t align_object_offset(intptr_t offset) { return align_size_up(offset, HeapWordsPerLong); } +// The expected size in bytes of a cache line, used to pad data structures. +#define DEFAULT_CACHE_LINE_SIZE 64 + +// Bytes needed to pad type to avoid cache-line sharing; alignment should be the +// expected cache line size (a power of two). The first addend avoids sharing +// when the start address is not a multiple of alignment; the second maintains +// alignment of starting addresses that happen to be a multiple. +#define PADDING_SIZE(type, alignment) \ + ((alignment) + align_size_up_(sizeof(type), alignment)) + +// Templates to create a subclass padded to avoid cache line sharing. These are +// effective only when applied to derived-most (leaf) classes. + +// When no args are passed to the base ctor. +template +class Padded: public T { +private: + char _pad_buf_[PADDING_SIZE(T, alignment)]; +}; + +// When either 0 or 1 args may be passed to the base ctor. +template +class Padded01: public T { +public: + Padded01(): T() { } + Padded01(Arg1T arg1): T(arg1) { } +private: + char _pad_buf_[PADDING_SIZE(T, alignment)]; +}; //---------------------------------------------------------------------------------------------------- // Utility macros for compilers diff --git a/hotspot/src/share/vm/utilities/taskqueue.cpp b/hotspot/src/share/vm/utilities/taskqueue.cpp index 66571581e64..7a001803d96 100644 --- a/hotspot/src/share/vm/utilities/taskqueue.cpp +++ b/hotspot/src/share/vm/utilities/taskqueue.cpp @@ -31,6 +31,48 @@ uint ParallelTaskTerminator::_total_spins = 0; uint ParallelTaskTerminator::_total_peeks = 0; #endif +#if TASKQUEUE_STATS +const char * const TaskQueueStats::_names[last_stat_id] = { + "qpush", "qpop", "qpop-s", "qattempt", "qsteal", "opush", "omax" +}; + +void TaskQueueStats::print_header(unsigned int line, outputStream* const stream, + unsigned int width) +{ + // Use a width w: 1 <= w <= max_width + const unsigned int max_width = 40; + const unsigned int w = MAX2(MIN2(width, max_width), 1U); + + if (line == 0) { // spaces equal in width to the header + const unsigned int hdr_width = w * last_stat_id + last_stat_id - 1; + stream->print("%*s", hdr_width, " "); + } else if (line == 1) { // labels + stream->print("%*s", w, _names[0]); + for (unsigned int i = 1; i < last_stat_id; ++i) { + stream->print(" %*s", w, _names[i]); + } + } else if (line == 2) { // dashed lines + char dashes[max_width + 1]; + memset(dashes, '-', w); + dashes[w] = '\0'; + stream->print("%s", dashes); + for (unsigned int i = 1; i < last_stat_id; ++i) { + stream->print(" %s", dashes); + } + } +} + +void TaskQueueStats::print(outputStream* stream, unsigned int width) const +{ + #define FMT SIZE_FORMAT_W(*) + stream->print(FMT, width, _stats[0]); + for (unsigned int i = 1; i < last_stat_id; ++i) { + stream->print(" " FMT, width, _stats[i]); + } + #undef FMT +} +#endif // TASKQUEUE_STATS + int TaskQueueSetSuper::randomParkAndMiller(int *seed0) { const int a = 16807; const int m = 2147483647; diff --git a/hotspot/src/share/vm/utilities/taskqueue.hpp b/hotspot/src/share/vm/utilities/taskqueue.hpp index 2deba1b9edb..52e89fc8027 100644 --- a/hotspot/src/share/vm/utilities/taskqueue.hpp +++ b/hotspot/src/share/vm/utilities/taskqueue.hpp @@ -22,6 +22,72 @@ * */ +// Simple TaskQueue stats that are collected by default in debug builds. + +#if !defined(TASKQUEUE_STATS) && defined(ASSERT) +#define TASKQUEUE_STATS 1 +#elif !defined(TASKQUEUE_STATS) +#define TASKQUEUE_STATS 0 +#endif + +#if TASKQUEUE_STATS +#define TASKQUEUE_STATS_ONLY(code) code +#else +#define TASKQUEUE_STATS_ONLY(code) +#endif // TASKQUEUE_STATS + +#if TASKQUEUE_STATS +class TaskQueueStats { +public: + enum StatId { + push, // number of taskqueue pushes + pop, // number of taskqueue pops + pop_slow, // subset of taskqueue pops that were done slow-path + steal_attempt, // number of taskqueue steal attempts + steal, // number of taskqueue steals + overflow, // number of overflow pushes + overflow_max_len, // max length of overflow stack + last_stat_id + }; + +public: + inline TaskQueueStats() { reset(); } + + inline void record_push() { ++_stats[push]; } + inline void record_pop() { ++_stats[pop]; } + inline void record_pop_slow() { record_pop(); ++_stats[pop_slow]; } + inline void record_steal(bool success); + inline void record_overflow(size_t new_length); + + inline size_t get(StatId id) const { return _stats[id]; } + inline const size_t* get() const { return _stats; } + + inline void reset(); + + static void print_header(unsigned int line, outputStream* const stream = tty, + unsigned int width = 10); + void print(outputStream* const stream = tty, unsigned int width = 10) const; + +private: + size_t _stats[last_stat_id]; + static const char * const _names[last_stat_id]; +}; + +void TaskQueueStats::record_steal(bool success) { + ++_stats[steal_attempt]; + if (success) ++_stats[steal]; +} + +void TaskQueueStats::record_overflow(size_t new_len) { + ++_stats[overflow]; + if (new_len > _stats[overflow_max_len]) _stats[overflow_max_len] = new_len; +} + +void TaskQueueStats::reset() { + memset(_stats, 0, sizeof(_stats)); +} +#endif // TASKQUEUE_STATS + template class TaskQueueSuper: public CHeapObj { protected: @@ -135,6 +201,8 @@ public: // Total size of queue. static const uint total_size() { return N; } + + TASKQUEUE_STATS_ONLY(TaskQueueStats stats;) }; template @@ -152,6 +220,7 @@ protected: public: using TaskQueueSuper::max_elems; using TaskQueueSuper::size; + TASKQUEUE_STATS_ONLY(using TaskQueueSuper::stats;) private: // Slow paths for push, pop_local. (pop_global has no fast path.) @@ -224,14 +293,14 @@ bool GenericTaskQueue::push_slow(E t, uint dirty_n_elems) { // g++ complains if the volatile result of the assignment is unused. const_cast(_elems[localBot] = t); OrderAccess::release_store(&_bottom, increment_index(localBot)); + TASKQUEUE_STATS_ONLY(stats.record_push()); return true; } return false; } template -bool GenericTaskQueue:: -pop_local_slow(uint localBot, Age oldAge) { +bool GenericTaskQueue::pop_local_slow(uint localBot, Age oldAge) { // This queue was observed to contain exactly one element; either this // thread will claim it, or a competing "pop_global". In either case, // the queue will be logically empty afterwards. Create a new Age value @@ -251,6 +320,7 @@ pop_local_slow(uint localBot, Age oldAge) { if (tempAge == oldAge) { // We win. assert(dirty_size(localBot, _age.top()) != N - 1, "sanity"); + TASKQUEUE_STATS_ONLY(stats.record_pop_slow()); return true; } } @@ -306,6 +376,8 @@ public: typedef GrowableArray overflow_t; typedef GenericTaskQueue taskqueue_t; + TASKQUEUE_STATS_ONLY(using taskqueue_t::stats;) + OverflowTaskQueue(); ~OverflowTaskQueue(); void initialize(); @@ -356,6 +428,7 @@ bool OverflowTaskQueue::push(E t) { if (!taskqueue_t::push(t)) { overflow_stack()->push(t); + TASKQUEUE_STATS_ONLY(stats.record_overflow(overflow_stack()->length())); } return true; } @@ -424,9 +497,13 @@ GenericTaskQueueSet::queue(uint i) { template bool GenericTaskQueueSet::steal(uint queue_num, int* seed, E& t) { - for (uint i = 0; i < 2 * _n; i++) - if (steal_best_of_2(queue_num, seed, t)) + for (uint i = 0; i < 2 * _n; i++) { + if (steal_best_of_2(queue_num, seed, t)) { + TASKQUEUE_STATS_ONLY(queue(queue_num)->stats.record_steal(true)); return true; + } + } + TASKQUEUE_STATS_ONLY(queue(queue_num)->stats.record_steal(false)); return false; } @@ -574,6 +651,7 @@ GenericTaskQueue::push(E t) { // g++ complains if the volatile result of the assignment is unused. const_cast(_elems[localBot] = t); OrderAccess::release_store(&_bottom, increment_index(localBot)); + TASKQUEUE_STATS_ONLY(stats.record_push()); return true; } else { return push_slow(t, dirty_n_elems); @@ -603,6 +681,7 @@ GenericTaskQueue::pop_local(E& t) { idx_t tp = _age.top(); // XXX if (size(localBot, tp) > 0) { assert(dirty_size(localBot, tp) != N - 1, "sanity"); + TASKQUEUE_STATS_ONLY(stats.record_pop()); return true; } else { // Otherwise, the queue contained exactly one element; we take the slow From 2dace6e70f197182d306686005ac0cc716ba7203 Mon Sep 17 00:00:00 2001 From: Weijun Wang Date: Mon, 19 Jul 2010 10:02:50 +0800 Subject: [PATCH 11/56] 6969683: Generify ResolverConfiguration codes Reviewed-by: alanb, chegar --- .../com/sun/jndi/dns/DnsContextFactory.java | 9 +-- .../sun/net/dns/ResolverConfiguration.java | 7 +- .../spi/nameservice/dns/DNSNameService.java | 78 +++++++++---------- .../net/dns/ResolverConfigurationImpl.java | 43 +++++----- .../net/dns/ResolverConfigurationImpl.java | 11 ++- 5 files changed, 73 insertions(+), 75 deletions(-) diff --git a/jdk/src/share/classes/com/sun/jndi/dns/DnsContextFactory.java b/jdk/src/share/classes/com/sun/jndi/dns/DnsContextFactory.java index c7a15dc6eec..c006ebdb5b9 100644 --- a/jdk/src/share/classes/com/sun/jndi/dns/DnsContextFactory.java +++ b/jdk/src/share/classes/com/sun/jndi/dns/DnsContextFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -132,7 +132,7 @@ public class DnsContextFactory implements InitialContextFactory { throw new ConfigurationException("DNS pseudo-URL required"); } - List servers = new ArrayList(); + List servers = new ArrayList<>(); for (int i = 0; i < urls.length; i++) { String server = urls[i].getHost(); @@ -142,7 +142,7 @@ public class DnsContextFactory implements InitialContextFactory { // No server or port given, so look to underlying platform. // ResolverConfiguration does some limited caching, so the // following is reasonably efficient even if called rapid-fire. - List platformServers = + List platformServers = ResolverConfiguration.open().nameservers(); if (!platformServers.isEmpty()) { servers.addAll(platformServers); @@ -157,8 +157,7 @@ public class DnsContextFactory implements InitialContextFactory { ? server : server + ":" + port); } - return (String[]) servers.toArray( - new String[servers.size()]); + return servers.toArray(new String[servers.size()]); } /* diff --git a/jdk/src/share/classes/sun/net/dns/ResolverConfiguration.java b/jdk/src/share/classes/sun/net/dns/ResolverConfiguration.java index e97d7fe0fe8..4ab30b2935d 100644 --- a/jdk/src/share/classes/sun/net/dns/ResolverConfiguration.java +++ b/jdk/src/share/classes/sun/net/dns/ResolverConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,6 @@ package sun.net.dns; import java.util.List; -import java.io.IOException; /** * The configuration of the client resolver. @@ -68,7 +67,7 @@ public abstract class ResolverConfiguration { * * @return list of domain names */ - public abstract List searchlist(); + public abstract List searchlist(); /** * Returns a list of name servers used for host name lookup. @@ -78,7 +77,7 @@ public abstract class ResolverConfiguration { * * @return list of the name servers */ - public abstract List nameservers(); + public abstract List nameservers(); /** diff --git a/jdk/src/share/classes/sun/net/spi/nameservice/dns/DNSNameService.java b/jdk/src/share/classes/sun/net/spi/nameservice/dns/DNSNameService.java index bdc82ad6da2..9142de0a3c0 100644 --- a/jdk/src/share/classes/sun/net/spi/nameservice/dns/DNSNameService.java +++ b/jdk/src/share/classes/sun/net/spi/nameservice/dns/DNSNameService.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,20 +45,21 @@ import sun.security.action.*; public final class DNSNameService implements NameService { // List of domains specified by property - private LinkedList domainList = null; + private LinkedList domainList = null; // JNDI-DNS URL for name servers specified via property private String nameProviderUrl = null; // Per-thread soft cache of the last temporary context - private static ThreadLocal contextRef = new ThreadLocal(); + private static ThreadLocal> contextRef = + new ThreadLocal<>(); // Simple class to encapsulate the temporary context private static class ThreadContext { private DirContext dirCtxt; - private List nsList; + private List nsList; - public ThreadContext(DirContext dirCtxt, List nsList) { + public ThreadContext(DirContext dirCtxt, List nsList) { this.dirCtxt = dirCtxt; this.nsList = nsList; } @@ -67,16 +68,16 @@ public final class DNSNameService implements NameService { return dirCtxt; } - public List nameservers() { + public List nameservers() { return nsList; } } // Returns a per-thread DirContext private DirContext getTemporaryContext() throws NamingException { - SoftReference ref = (SoftReference)contextRef.get(); + SoftReference ref = contextRef.get(); ThreadContext thrCtxt = null; - List nsList = null; + List nsList = null; // if no property specified we need to obtain the list of servers // @@ -87,7 +88,7 @@ public final class DNSNameService implements NameService { // specified then we need to check if the DNS configuration // has changed. // - if ((ref != null) && ((thrCtxt = (ThreadContext)ref.get()) != null)) { + if ((ref != null) && ((thrCtxt = ref.get()) != null)) { if (nameProviderUrl == null) { if (!thrCtxt.nameservers().equals(nsList)) { // DNS configuration has changed @@ -98,7 +99,7 @@ public final class DNSNameService implements NameService { // new thread context needs to be created if (thrCtxt == null) { - final Hashtable env = new Hashtable(); + final Hashtable env = new Hashtable<>(); env.put("java.naming.factory.initial", "com.sun.jndi.dns.DnsContextFactory"); @@ -119,10 +120,9 @@ public final class DNSNameService implements NameService { // DirContext dirCtxt; try { - dirCtxt = (DirContext) - java.security.AccessController.doPrivileged( - new java.security.PrivilegedExceptionAction() { - public Object run() throws NamingException { + dirCtxt = java.security.AccessController.doPrivileged( + new java.security.PrivilegedExceptionAction() { + public DirContext run() throws NamingException { // Create the DNS context using NamingManager rather than using // the initial context constructor. This avoids having the initial // context constructor call itself. @@ -130,7 +130,7 @@ public final class DNSNameService implements NameService { if (!(ctx instanceof DirContext)) { return null; // cannot create a DNS context } - return ctx; + return (DirContext)ctx; } }); } catch (java.security.PrivilegedActionException pae) { @@ -161,18 +161,18 @@ public final class DNSNameService implements NameService { * * @throws UnknownHostException if lookup fails or other error. */ - private ArrayList resolve(final DirContext ctx, final String name, final String[] ids, - int depth) throws UnknownHostException + private ArrayList resolve(final DirContext ctx, final String name, + final String[] ids, int depth) + throws UnknownHostException { - ArrayList results = new ArrayList(); + ArrayList results = new ArrayList<>(); Attributes attrs; // do the query try { - attrs = (Attributes) - java.security.AccessController.doPrivileged( - new java.security.PrivilegedExceptionAction() { - public Object run() throws NamingException { + attrs = java.security.AccessController.doPrivileged( + new java.security.PrivilegedExceptionAction() { + public Attributes run() throws NamingException { return ctx.getAttributes(name, ids); } }); @@ -181,7 +181,7 @@ public final class DNSNameService implements NameService { } // non-requested type returned so enumeration is empty - NamingEnumeration ne = attrs.getAll(); + NamingEnumeration ne = attrs.getAll(); if (!ne.hasMoreElements()) { throw new UnknownHostException("DNS record not found"); } @@ -190,7 +190,7 @@ public final class DNSNameService implements NameService { UnknownHostException uhe = null; try { while (ne.hasMoreElements()) { - Attribute attr = (Attribute)ne.next(); + Attribute attr = ne.next(); String attrID = attr.getID(); for (NamingEnumeration e = attr.getAll(); e.hasMoreElements();) { @@ -251,13 +251,12 @@ public final class DNSNameService implements NameService { // no property specified so check host DNS resolver configured // with at least one nameserver in dotted notation. // - List nsList = ResolverConfiguration.open().nameservers(); - if (nsList.size() == 0) + List nsList = ResolverConfiguration.open().nameservers(); + if (nsList.isEmpty()) { throw new RuntimeException("no nameservers provided"); + } boolean found = false; - Iterator i = nsList.iterator(); - while (i.hasNext()) { - String addr = (String)i.next(); + for (String addr: nsList) { if (IPAddressUtil.isIPv4LiteralAddress(addr) || IPAddressUtil.isIPv6LiteralAddress(addr)) { found = true; @@ -308,8 +307,8 @@ public final class DNSNameService implements NameService { // suffix if the list has one entry. if (results == null) { - List searchList = null; - Iterator i; + List searchList = null; + Iterator i; boolean usingSearchList = false; if (domainList != null) { @@ -324,7 +323,7 @@ public final class DNSNameService implements NameService { // iterator through each domain suffix while (i.hasNext()) { - String parentDomain = (String)i.next(); + String parentDomain = i.next(); int start = 0; while ((start = parentDomain.indexOf(".")) != -1 && start < parentDomain.length() -1) { @@ -407,7 +406,7 @@ public final class DNSNameService implements NameService { String literalip = ""; String[] ids = { "PTR" }; DirContext ctx; - ArrayList results = null; + ArrayList results = null; try { ctx = getTemporaryContext(); } catch (NamingException nx) { @@ -420,7 +419,7 @@ public final class DNSNameService implements NameService { literalip += "IN-ADDR.ARPA."; results = resolve(ctx, literalip, ids, 0); - host = (String)results.get(0); + host = results.get(0); } else if (addr.length == 16) { // IPv6 Address /** * Because RFC 3152 changed the root domain name for reverse @@ -437,7 +436,7 @@ public final class DNSNameService implements NameService { try { results = resolve(ctx, ip6lit, ids, 0); - host = (String)results.get(0); + host = results.get(0); } catch (UnknownHostException e) { host = null; } @@ -445,7 +444,7 @@ public final class DNSNameService implements NameService { // IP6.ARPA lookup failed, let's try the older IP6.INT ip6lit = literalip + "IP6.INT."; results = resolve(ctx, ip6lit, ids, 0); - host = (String)results.get(0); + host = results.get(0); } } } catch (Exception e) { @@ -478,11 +477,10 @@ public final class DNSNameService implements NameService { * @return String containing the JNDI-DNS provider URL * corresponding to the supplied List of nameservers. */ - private static String createProviderURL(List nsList) { - Iterator i = nsList.iterator(); + private static String createProviderURL(List nsList) { StringBuffer sb = new StringBuffer(); - while (i.hasNext()) { - appendIfLiteralAddress((String)i.next(), sb); + for (String s: nsList) { + appendIfLiteralAddress(s, sb); } return sb.toString(); } diff --git a/jdk/src/solaris/classes/sun/net/dns/ResolverConfigurationImpl.java b/jdk/src/solaris/classes/sun/net/dns/ResolverConfigurationImpl.java index ed984e32571..3695b5d368b 100644 --- a/jdk/src/solaris/classes/sun/net/dns/ResolverConfigurationImpl.java +++ b/jdk/src/solaris/classes/sun/net/dns/ResolverConfigurationImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -56,8 +56,11 @@ public class ResolverConfigurationImpl // Parse /etc/resolv.conf to get the values for a particular // keyword. // - private LinkedList resolvconf(String keyword, int maxperkeyword, int maxkeywords) { - LinkedList ll = new LinkedList(); + private LinkedList resolvconf(String keyword, + int maxperkeyword, + int maxkeywords) + { + LinkedList ll = new LinkedList<>(); try { BufferedReader in = @@ -99,8 +102,8 @@ public class ResolverConfigurationImpl return ll; } - private LinkedList searchlist; - private LinkedList nameservers; + private LinkedList searchlist; + private LinkedList nameservers; // Load DNS configuration from OS @@ -118,9 +121,9 @@ public class ResolverConfigurationImpl // get the name servers from /etc/resolv.conf nameservers = - (LinkedList)java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Object run() { + java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction>() { + public LinkedList run() { // typically MAXNS is 3 but we've picked 5 here // to allow for additional servers if required. return resolvconf("nameserver", 1, 5); @@ -137,15 +140,15 @@ public class ResolverConfigurationImpl // obtain search list or local domain - private LinkedList getSearchList() { + private LinkedList getSearchList() { - LinkedList sl; + LinkedList sl; // first try the search keyword in /etc/resolv.conf - sl = (LinkedList)java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Object run() { + sl = java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction>() { + public LinkedList run() { LinkedList ll; // first try search keyword (max 6 domains) @@ -177,10 +180,10 @@ public class ResolverConfigurationImpl // try domain keyword in /etc/resolv.conf - sl = (LinkedList)java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Object run() { - LinkedList ll; + sl = java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction>() { + public LinkedList run() { + LinkedList ll; ll = resolvconf("domain", 1, 1); if (ll.size() > 0) { @@ -197,7 +200,7 @@ public class ResolverConfigurationImpl // no local domain so try fallback (RPC) domain or // hostname - sl = new LinkedList(); + sl = new LinkedList<>(); String domain = fallbackDomain0(); if (domain != null && domain.length() > 0) { sl.add(domain); @@ -213,7 +216,7 @@ public class ResolverConfigurationImpl opts = new OptionsImpl(); } - public List searchlist() { + public List searchlist() { synchronized (lock) { loadConfig(); @@ -222,7 +225,7 @@ public class ResolverConfigurationImpl } } - public List nameservers() { + public List nameservers() { synchronized (lock) { loadConfig(); diff --git a/jdk/src/windows/classes/sun/net/dns/ResolverConfigurationImpl.java b/jdk/src/windows/classes/sun/net/dns/ResolverConfigurationImpl.java index 87c3ff3d962..79708856036 100644 --- a/jdk/src/windows/classes/sun/net/dns/ResolverConfigurationImpl.java +++ b/jdk/src/windows/classes/sun/net/dns/ResolverConfigurationImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,7 +28,6 @@ package sun.net.dns; import java.util.List; import java.util.LinkedList; import java.util.StringTokenizer; -import java.io.IOException; /* * An implementation of sun.net.ResolverConfiguration for Windows. @@ -63,8 +62,8 @@ public class ResolverConfigurationImpl // Parse string that consists of token delimited by space or commas // and return LinkedHashMap - private LinkedList stringToList(String str) { - LinkedList ll = new LinkedList(); + private LinkedList stringToList(String str) { + LinkedList ll = new LinkedList<>(); // comma and space are valid delimites StringTokenizer st = new StringTokenizer(str, ", "); @@ -112,7 +111,7 @@ public class ResolverConfigurationImpl opts = new OptionsImpl(); } - public List searchlist() { + public List searchlist() { synchronized (lock) { loadConfig(); @@ -121,7 +120,7 @@ public class ResolverConfigurationImpl } } - public List nameservers() { + public List nameservers() { synchronized (lock) { loadConfig(); From f2f06cfb5d1b9034c5902513a59ead1af9c3ebcd Mon Sep 17 00:00:00 2001 From: Weijun Wang Date: Mon, 19 Jul 2010 10:02:55 +0800 Subject: [PATCH 12/56] 6969292: make DNS lookup for realm/kdc really work Reviewed-by: alanb, valeriep --- .../classes/sun/security/krb5/Config.java | 60 +++++++++++++------ 1 file changed, 43 insertions(+), 17 deletions(-) diff --git a/jdk/src/share/classes/sun/security/krb5/Config.java b/jdk/src/share/classes/sun/security/krb5/Config.java index c885869ff65..21fb4cea7f5 100644 --- a/jdk/src/share/classes/sun/security/krb5/Config.java +++ b/jdk/src/share/classes/sun/security/krb5/Config.java @@ -42,6 +42,8 @@ import java.util.Enumeration; import java.util.StringTokenizer; import java.net.InetAddress; import java.net.UnknownHostException; +import java.util.List; +import sun.net.dns.ResolverConfiguration; import sun.security.krb5.internal.crypto.EType; import sun.security.krb5.internal.ktab.*; import sun.security.krb5.internal.Krb5; @@ -1180,6 +1182,33 @@ public class Config { } // get the domain realm mapping from the configuration String mapRealm = PrincipalName.mapHostToRealm(hostName); + if (mapRealm == null) { + // No match. Try search and/or domain in /etc/resolv.conf + List srchlist = ResolverConfiguration.open().searchlist(); + for (String domain: srchlist) { + realm = checkRealm(domain); + if (realm != null) { + break; + } + } + } else { + realm = checkRealm(mapRealm); + } + if (realm == null) { + throw new KrbException(Krb5.KRB_ERR_GENERIC, + "Unable to locate Kerberos realm"); + } + return realm; + } + + /** + * Check if the provided realm is the correct realm + * @return the realm if correct, or null otherwise + */ + private static String checkRealm(String mapRealm) { + if (DEBUG) { + System.out.println("getRealmFromDNS: trying " + mapRealm); + } String[] records = null; String newRealm = mapRealm; while ((records == null) && (newRealm != null)) { @@ -1188,23 +1217,14 @@ public class Config { newRealm = Realm.parseRealmComponent(newRealm); // if no DNS TXT records found, try again using sub-realm } - if (records == null) { - // no DNS TXT records - throw new KrbException(Krb5.KRB_ERR_GENERIC, - "Unable to locate Kerberos realm"); - } - boolean found = false; - for (int i = 0; i < records.length; i++) { - if (records[i].equals(mapRealm)) { - found = true; - realm = records[i]; + if (records != null) { + for (int i = 0; i < records.length; i++) { + if (records[i].equalsIgnoreCase(mapRealm)) { + return records[i]; + } } } - if (found == false) { - throw new KrbException(Krb5.KRB_ERR_GENERIC, - "Unable to locate Kerberos realm"); - } - return realm; + return null; } /** @@ -1218,10 +1238,16 @@ public class Config { String kdcs = null; String[] srvs = null; // locate DNS SRV record using UDP - srvs = KrbServiceLocator.getKerberosService(realm, "_udp."); + if (DEBUG) { + System.out.println("getKDCFromDNS using UDP"); + } + srvs = KrbServiceLocator.getKerberosService(realm, "_udp"); if (srvs == null) { // locate DNS SRV record using TCP - srvs = KrbServiceLocator.getKerberosService(realm, "_tcp."); + if (DEBUG) { + System.out.println("getKDCFromDNS using UDP"); + } + srvs = KrbServiceLocator.getKerberosService(realm, "_tcp"); } if (srvs == null) { // no DNS SRV records From 5c3da1ee7eecc8f6e4eafedaaa1b5304c57799c5 Mon Sep 17 00:00:00 2001 From: John Cuthbertson Date: Mon, 19 Jul 2010 11:06:34 -0700 Subject: [PATCH 13/56] 6956639: G1: assert(cached_ptr != card_ptr) failed: shouldn't be, concurrentG1Refine.cpp:307 During concurrent refinment, filter cards in young regions after it has been determined that the region has been allocated from and the young type of the region has been set. Reviewed-by: iveresov, tonyp, jcoomes --- .../g1/concurrentG1Refine.cpp | 64 ++++++++----------- .../gc_implementation/g1/g1CollectedHeap.cpp | 5 ++ .../vm/gc_implementation/g1/g1RemSet.cpp | 32 ++++++++-- .../vm/gc_implementation/g1/heapRegion.cpp | 13 +++- .../vm/gc_implementation/g1/heapRegion.hpp | 7 +- 5 files changed, 75 insertions(+), 46 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp index 7652a5f05e4..78d3d5cb2cd 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -271,21 +271,16 @@ jbyte* ConcurrentG1Refine::add_card_count(jbyte* card_ptr, int* count, bool* def if (cas_res == prev_epoch_entry) { // We successfully updated the card num value in the epoch entry count_ptr->_count = 0; // initialize counter for new card num + jbyte* old_card_ptr = card_num_2_ptr(old_card_num); // Even though the region containg the card at old_card_num was not // in the young list when old_card_num was recorded in the epoch // cache it could have been added to the free list and subsequently - // added to the young list in the intervening time. If the evicted - // card is in a young region just return the card_ptr and the evicted - // card will not be cleaned. See CR 6817995. - - jbyte* old_card_ptr = card_num_2_ptr(old_card_num); - if (is_young_card(old_card_ptr)) { - *count = 0; - // We can defer the processing of card_ptr - *defer = true; - return card_ptr; - } + // added to the young list in the intervening time. See CR 6817995. + // We do not deal with this case here - it will be handled in + // HeapRegion::oops_on_card_seq_iterate_careful after it has been + // determined that the region containing the card has been allocated + // to, and it's safe to check the young type of the region. // We do not want to defer processing of card_ptr in this case // (we need to refine old_card_ptr and card_ptr) @@ -301,22 +296,22 @@ jbyte* ConcurrentG1Refine::cache_insert(jbyte* card_ptr, bool* defer) { jbyte* cached_ptr = add_card_count(card_ptr, &count, defer); assert(cached_ptr != NULL, "bad cached card ptr"); - if (is_young_card(cached_ptr)) { - // The region containing cached_ptr has been freed during a clean up - // pause, reallocated, and tagged as young. - assert(cached_ptr != card_ptr, "shouldn't be"); + // We've just inserted a card pointer into the card count cache + // and got back the card that we just inserted or (evicted) the + // previous contents of that count slot. - // We've just inserted a new old-gen card pointer into the card count - // cache and evicted the previous contents of that count slot. - // The evicted card pointer has been determined to be in a young region - // and so cannot be the newly inserted card pointer (that will be - // in an old region). - // The count for newly inserted card will be set to zero during the - // insertion, so we don't want to defer the cleaning of the newly - // inserted card pointer. - assert(*defer == false, "deferring non-hot card"); - return NULL; - } + // The card we got back could be in a young region. When the + // returned card (if evicted) was originally inserted, we had + // determined that its containing region was not young. However + // it is possible for the region to be freed during a cleanup + // pause, then reallocated and tagged as young which will result + // in the returned card residing in a young region. + // + // We do not deal with this case here - the change from non-young + // to young could be observed at any time - it will be handled in + // HeapRegion::oops_on_card_seq_iterate_careful after it has been + // determined that the region containing the card has been allocated + // to. // The card pointer we obtained from card count cache is not hot // so do not store it in the cache; return it for immediate @@ -325,7 +320,7 @@ jbyte* ConcurrentG1Refine::cache_insert(jbyte* card_ptr, bool* defer) { return cached_ptr; } - // Otherwise, the pointer we got from the _card_counts is hot. + // Otherwise, the pointer we got from the _card_counts cache is hot. jbyte* res = NULL; MutexLockerEx x(HotCardCache_lock, Mutex::_no_safepoint_check_flag); if (_n_hot == _hot_cache_size) { @@ -338,17 +333,8 @@ jbyte* ConcurrentG1Refine::cache_insert(jbyte* card_ptr, bool* defer) { if (_hot_cache_idx == _hot_cache_size) _hot_cache_idx = 0; _n_hot++; - if (res != NULL) { - // Even though the region containg res was not in the young list - // when it was recorded in the hot cache it could have been added - // to the free list and subsequently added to the young list in - // the intervening time. If res is in a young region, return NULL - // so that res is not cleaned. See CR 6817995. - - if (is_young_card(res)) { - res = NULL; - } - } + // The card obtained from the hot card cache could be in a young + // region. See above on how this can happen. return res; } diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp index 79622015207..658ac777f49 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @@ -638,6 +638,11 @@ G1CollectedHeap::attempt_allocation_slow(size_t word_size, // Now retry the allocation. if (_cur_alloc_region != NULL) { + if (allocated_young_region != NULL) { + // We need to ensure that the store to top does not + // float above the setting of the young type. + OrderAccess::storestore(); + } res = _cur_alloc_region->allocate(word_size); } } diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp index 5de8d9e61f6..a3a77ed186b 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -676,9 +676,27 @@ void HRInto_G1RemSet::concurrentRefineOneCard_impl(jbyte* card_ptr, int worker_i // We must complete this write before we do any of the reads below. OrderAccess::storeload(); // And process it, being careful of unallocated portions of TLAB's. + + // The region for the current card may be a young region. The + // current card may have been a card that was evicted from the + // card cache. When the card was inserted into the cache, we had + // determined that its region was non-young. While in the cache, + // the region may have been freed during a cleanup pause, reallocated + // and tagged as young. + // + // We wish to filter out cards for such a region but the current + // thread, if we're running conucrrently, may "see" the young type + // change at any time (so an earlier "is_young" check may pass or + // fail arbitrarily). We tell the iteration code to perform this + // filtering when it has been determined that there has been an actual + // allocation in this region and making it safe to check the young type. + bool filter_young = true; + HeapWord* stop_point = r->oops_on_card_seq_iterate_careful(dirtyRegion, - &filter_then_update_rs_oop_cl); + &filter_then_update_rs_oop_cl, + filter_young); + // If stop_point is non-null, then we encountered an unallocated region // (perhaps the unfilled portion of a TLAB.) For now, we'll dirty the // card and re-enqueue: if we put off the card until a GC pause, then the @@ -789,8 +807,14 @@ void HRInto_G1RemSet::concurrentRefineOneCard(jbyte* card_ptr, int worker_i) { if (r == NULL) { assert(_g1->is_in_permanent(start), "Or else where?"); } else { - guarantee(!r->is_young(), "It was evicted in the current minor cycle."); - // Process card pointer we get back from the hot card cache + // Checking whether the region we got back from the cache + // is young here is inappropriate. The region could have been + // freed, reallocated and tagged as young while in the cache. + // Hence we could see its young type change at any time. + // + // Process card pointer we get back from the hot card cache. This + // will check whether the region containing the card is young + // _after_ checking that the region has been allocated from. concurrentRefineOneCard_impl(res, worker_i); } } diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp index 74541915ef3..4e5446e1f5e 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp @@ -658,7 +658,8 @@ HeapRegion::object_iterate_mem_careful(MemRegion mr, HeapWord* HeapRegion:: oops_on_card_seq_iterate_careful(MemRegion mr, - FilterOutOfRegionClosure* cl) { + FilterOutOfRegionClosure* cl, + bool filter_young) { G1CollectedHeap* g1h = G1CollectedHeap::heap(); // If we're within a stop-world GC, then we might look at a card in a @@ -672,6 +673,16 @@ oops_on_card_seq_iterate_careful(MemRegion mr, if (mr.is_empty()) return NULL; // Otherwise, find the obj that extends onto mr.start(). + // The intersection of the incoming mr (for the card) and the + // allocated part of the region is non-empty. This implies that + // we have actually allocated into this region. The code in + // G1CollectedHeap.cpp that allocates a new region sets the + // is_young tag on the region before allocating. Thus we + // safely know if this region is young. + if (is_young() && filter_young) { + return NULL; + } + // We used to use "block_start_careful" here. But we're actually happy // to update the BOT while we do this... HeapWord* cur = block_start(mr.start()); diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp index c8768c24267..42e96bbfb50 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp @@ -252,7 +252,7 @@ class HeapRegion: public G1OffsetTableContigSpace { // survivor }; - YoungType _young_type; + volatile YoungType _young_type; int _young_index_in_cset; SurvRateGroup* _surv_rate_group; int _age_index; @@ -726,9 +726,12 @@ class HeapRegion: public G1OffsetTableContigSpace { HeapWord* object_iterate_mem_careful(MemRegion mr, ObjectClosure* cl); + // In this version - if filter_young is true and the region + // is a young region then we skip the iteration. HeapWord* oops_on_card_seq_iterate_careful(MemRegion mr, - FilterOutOfRegionClosure* cl); + FilterOutOfRegionClosure* cl, + bool filter_young); // The region "mr" is entirely in "this", and starts and ends at block // boundaries. The caller declares that all the contained blocks are From 882b752caff7bdea7e84dc865cb75311afb76cbe Mon Sep 17 00:00:00 2001 From: Sean Mullan Date: Tue, 20 Jul 2010 10:41:50 -0400 Subject: [PATCH 14/56] 6870553: X509Certificate.getSigAlgName method description uses non-standard algorithm name as example Reviewed-by: xuelei --- jdk/src/share/classes/java/security/cert/X509CRL.java | 4 ++-- jdk/src/share/classes/java/security/cert/X509Certificate.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/jdk/src/share/classes/java/security/cert/X509CRL.java b/jdk/src/share/classes/java/security/cert/X509CRL.java index c9934def8d9..0998f364fcd 100644 --- a/jdk/src/share/classes/java/security/cert/X509CRL.java +++ b/jdk/src/share/classes/java/security/cert/X509CRL.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -387,7 +387,7 @@ public abstract class X509CRL extends CRL implements X509Extension { /** * Gets the signature algorithm name for the CRL - * signature algorithm. An example is the string "SHA-1/DSA". + * signature algorithm. An example is the string "SHA256withRSA". * The ASN.1 definition for this is: *

          * signatureAlgorithm   AlgorithmIdentifier

    diff --git a/jdk/src/share/classes/java/security/cert/X509Certificate.java b/jdk/src/share/classes/java/security/cert/X509Certificate.java index 8ca8c5d4d66..cb0e5482433 100644 --- a/jdk/src/share/classes/java/security/cert/X509Certificate.java +++ b/jdk/src/share/classes/java/security/cert/X509Certificate.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -352,7 +352,7 @@ implements X509Extension { /** * Gets the signature algorithm name for the certificate - * signature algorithm. An example is the string "SHA-1/DSA". + * signature algorithm. An example is the string "SHA256withRSA". * The ASN.1 definition for this is: *

          * signatureAlgorithm   AlgorithmIdentifier

    From 2890d62dbbe0435362d579b12669acdebc763724 Mon Sep 17 00:00:00 2001 From: Chris Hegarty Date: Wed, 21 Jul 2010 13:29:26 +0100 Subject: [PATCH 15/56] 6969395: TEST_BUG: Tests in java/net sun/net problems Reviewed-by: alanb --- jdk/test/ProblemList.txt | 133 ---------------- jdk/test/com/sun/net/httpserver/Test1.java | 4 +- jdk/test/com/sun/net/httpserver/Test11.java | 36 ++--- jdk/test/com/sun/net/httpserver/Test12.java | 4 +- jdk/test/com/sun/net/httpserver/Test13.java | 5 +- jdk/test/com/sun/net/httpserver/Test6a.java | 4 +- jdk/test/com/sun/net/httpserver/Test7a.java | 5 +- jdk/test/com/sun/net/httpserver/Test8a.java | 83 +++++----- jdk/test/com/sun/net/httpserver/Test9.java | 4 +- jdk/test/com/sun/net/httpserver/Test9a.java | 4 +- .../com/sun/net/httpserver/bugs/B6361557.java | 7 +- .../com/sun/net/httpserver/bugs/B6373555.java | 4 +- .../net/DatagramSocket/DatagramTimeout.java | 14 +- .../java/net/DatagramSocket/SendSize.java | 48 ++---- jdk/test/java/net/Inet6Address/B6558853.java | 4 + .../net/Inet6Address/serialize/Serialize.java | 4 + jdk/test/java/net/InetAddress/CheckJNI.java | 2 + .../net/MulticastSocket/SetOutgoingIf.java | 4 + jdk/test/java/net/ResponseCache/B6181108.java | 4 +- .../net/ResponseCache/ResponseCacheTest.java | 26 +++- .../net/ResponseCache/getResponseCode.java | 5 + jdk/test/java/net/Socket/AccurateTimeout.java | 144 ------------------ jdk/test/java/net/Socket/CloseAvailable.java | 3 +- jdk/test/java/net/Socket/DeadlockTest.java | 59 +++---- jdk/test/java/net/Socket/LingerTest.java | 8 +- jdk/test/java/net/Socket/LinkLocal.java | 18 ++- jdk/test/java/net/Socket/ProxyCons.java | 10 +- jdk/test/java/net/Socket/ReadTimeout.java | 10 +- .../java/net/Socket/SetReceiveBufferSize.java | 19 +-- jdk/test/java/net/Socket/SetSoLinger.java | 32 ++-- jdk/test/java/net/Socket/ShutdownBoth.java | 14 +- jdk/test/java/net/Socket/SoTimeout.java | 7 +- jdk/test/java/net/Socket/Timeout.java | 8 +- jdk/test/java/net/Socket/UrgentDataTest.java | 107 ++++++------- .../net/Socket/asyncClose/BrokenPipe.java | 4 +- .../net/Socket/setReuseAddress/Restart.java | 37 ++--- .../SocketClosedException.java | 84 +++------- .../net/SocketInputStream/SocketTimeout.java | 28 ++-- jdk/test/java/net/URL/GetContent.java | 6 +- .../java/net/URLClassLoader/ClassLoad.java | 31 +++- .../net/URLConnection/DisconnectAfterEOF.java | 5 +- .../HandleContentTypeWithAttrs.java | 10 +- .../HttpContinueStackOverflow.java | 45 +++--- .../net/URLConnection/Redirect307Test.java | 27 ++-- .../java/net/URLConnection/RedirectLimit.java | 4 + .../net/URLConnection/ResendPostBody.java | 8 +- .../net/URLConnection/SetIfModifiedSince.java | 2 +- .../java/net/URLConnection/TimeoutTest.java | 8 +- .../URLConnection/URLConnectionHeaders.java | 6 +- .../net/URLConnection/ZeroContentLength.java | 60 ++++++-- jdk/test/java/net/ipv6tests/B6521014.java | 2 + jdk/test/java/net/ipv6tests/TcpTest.java | 23 --- jdk/test/java/net/ipv6tests/Tests.java | 6 +- jdk/test/sun/net/ftp/FtpGetContent.java | 20 +-- jdk/test/sun/net/ftp/FtpURL.java | 17 +-- ...hunkedEncodingWithProgressMonitorTest.java | 6 +- .../www/http/ChunkedOutputStream/Test.java | 30 ++-- .../sun/net/www/http/HttpClient/B6726695.java | 2 + .../www/http/HttpClient/MultiThreadTest.java | 11 +- .../net/www/http/HttpClient/ProxyTest.java | 52 +++---- .../KeepAliveCache/KeepAliveTimerThread.java | 5 +- ...liveStreamCloseWithWrongContentLength.java | 20 +-- jdk/test/sun/net/www/httptest/HttpServer.java | 6 + .../sun/net/www/protocol/http/DigestTest.java | 21 +-- 64 files changed, 571 insertions(+), 858 deletions(-) delete mode 100644 jdk/test/java/net/Socket/AccurateTimeout.java diff --git a/jdk/test/ProblemList.txt b/jdk/test/ProblemList.txt index 748bcd86810..b8769c97078 100644 --- a/jdk/test/ProblemList.txt +++ b/jdk/test/ProblemList.txt @@ -369,139 +369,6 @@ javax/print/attribute/MediaMappingsTest.java generic-all # jdk_net -# Suspect many of these tests auffer from using fixed ports, no concrete -# evidence. - -# Times out on Windows X64 -sun/net/www/http/KeepAliveStream/KeepAliveStreamCloseWithWrongContentLength.java generic-all - -# Dies on Solaris 10 sparc and sparcv9, Linux -ea -esa with -# Interrupted or IO exception, maybe writing to non-unique named file? -com/sun/net/httpserver/bugs/B6373555.java generic-all - -# Fails on OpenSolaris, times out -java/net/MulticastSocket/SetOutgoingIf.java generic-all - -# Timed out on Solaris 10 X86. -com/sun/net/httpserver/Test3.java generic-all - -# Exception in test on windows -com/sun/net/httpserver/bugs/B6373555.java windows-all - -# One of these pollutes the samevm on Linux, too many open files, kills jtreg -com/sun/net/httpserver/bugs/B6339483.java generic-all -com/sun/net/httpserver/bugs/B6341616.java generic-all - -# Suspects in cascading samevm problem, solaris 11 i586 (needs othervm?) -# Suspect use of setHttps*()? -com/sun/net/httpserver/SelCacheTest.java generic-all -com/sun/net/httpserver/Test1.java generic-all -com/sun/net/httpserver/Test12.java generic-all -com/sun/net/httpserver/Test13.java generic-all -com/sun/net/httpserver/Test6a.java generic-all -com/sun/net/httpserver/Test7a.java generic-all -com/sun/net/httpserver/Test8a.java generic-all -com/sun/net/httpserver/Test9.java generic-all -com/sun/net/httpserver/Test9a.java generic-all - -# 10,000 connections, fails on Linux and makes tests&jtreg fail with samevm -com/sun/net/httpserver/bugs/B6361557.java generic-all - -# Address already in use with samevm? Always? Solaris sparc, probably ports -java/net/Authenticator/B4933582.sh generic-all -java/net/DatagramSocket/SendSize.java generic-all - -# Solaris 11: exception wrong address??? -java/net/Inet6Address/B6558853.java generic-all - -# Not closing stream on file i6a1, windows samevm problem -java/net/Inet6Address/serialize/Serialize.java generic-all - -# Linux x64 fails "network unreachable"? -java/net/ipv6tests/TcpTest.java generic-all - -# Linux i586, fails with unexpected output -java/net/MulticastSocket/NoLoopbackPackets.java linux-i586 - -# Address already in use -java/net/DatagramSocket/DatagramTimeout.java generic-all - -# Fails on windows, takes too long and fails -# Solaris 10 sparcv9, samevm, java.lang.Exception: Takes too long. Dead lock -java/net/Socket/DeadlockTest.java generic-all - -# Linux i586 address already in use or connection error, samevm issues -java/net/Socket/AccurateTimeout.java generic-all -java/net/Socket/asyncClose/BrokenPipe.java generic-all -java/net/Socket/CloseAvailable.java generic-all - -# Linux X64 address already in use, samevm issues -java/net/Socket/LingerTest.java generic-all -java/net/Socket/LinkLocal.java generic-all -java/net/Socket/NullHost.java generic-all -java/net/Socket/ProxyCons.java generic-all -java/net/Socket/ReadTimeout.java generic-all - -# Linux X64 address already in use, samevm issues -java/net/Socket/SetReceiveBufferSize.java generic-all - -# Linux i586 address already in use or connection error, samevm issues -java/net/Socket/setReuseAddress/Basic.java generic-all -java/net/Socket/setReuseAddress/Restart.java generic-all - -# Linux X64 address already in use, samevm issues -java/net/Socket/SetSoLinger.java generic-all - -# Address already in use, windows samevm -java/net/Socket/Timeout.java generic-all - -# Linux X64 address already in use, samevm issues -java/net/Socket/ShutdownBoth.java generic-all -java/net/Socket/SoTimeout.java generic-all -java/net/Socket/TestClose.java generic-all -java/net/Socket/UrgentDataTest.java generic-all -java/net/SocketInputStream/SocketClosedException.java generic-all -java/net/SocketInputStream/SocketTimeout.java generic-all - -# Linux i586, address already in use or timeout, samevm issues -java/net/URLConnection/DisconnectAfterEOF.java generic-all -java/net/URLConnection/HandleContentTypeWithAttrs.java generic-all -java/net/URLConnection/Responses.java generic-all -java/net/URLConnection/TimeoutTest.java generic-all -java/net/URLConnection/ZeroContentLength.java generic-all - -# Solaris 11 i586 fails with samevm, not sure why -java/net/ResponseCache/B6181108.java generic-all -java/net/ResponseCache/ResponseCacheTest.java generic-all -java/net/URL/GetContent.java generic-all -java/net/URLConnection/HttpContinueStackOverflow.java generic-all -java/net/URLConnection/Redirect307Test.java generic-all -java/net/URLConnection/RedirectLimit.java generic-all -java/net/URLConnection/ResendPostBody.java generic-all -java/net/URL/OpenStream.java generic-all -java/net/URLClassLoader/ClassLoad.java generic-all -java/net/URLConnection/SetIfModifiedSince.java generic-all -java/net/URLConnection/URLConnectionHeaders.java generic-all - -# Linux i586 Connection refused or address already in use, samevm issues -sun/net/ftp/B6427768.java generic-all -sun/net/ftp/FtpGetContent.java generic-all -sun/net/ftp/FtpURL.java generic-all - -# Failed on solaris 10 i586, Exception: should have gotten HttpRetryException? -sun/net/www/http/ChunkedOutputStream/Test.java generic-all - -# Trouble cleaning up threads in samevm mode on solaris 11 i586 -sun/net/www/http/HttpClient/ProxyTest.java generic-all -sun/net/www/http/ChunkedInputStream/ChunkedEncodingTest.java generic-all -sun/net/www/http/ChunkedInputStream/ChunkedEncodingWithProgressMonitorTest.java generic-all -sun/net/www/http/HttpClient/B6726695.java generic-all -sun/net/www/http/HttpClient/MultiThreadTest.java generic-all -sun/net/www/http/KeepAliveCache/KeepAliveTimerThread.java generic-all - -# Connection refused, windows samevm -sun/net/www/protocol/http/DigestTest.java generic-all - ############################################################################ # jdk_io diff --git a/jdk/test/com/sun/net/httpserver/Test1.java b/jdk/test/com/sun/net/httpserver/Test1.java index 786b94eda4d..e58900e0f7d 100644 --- a/jdk/test/com/sun/net/httpserver/Test1.java +++ b/jdk/test/com/sun/net/httpserver/Test1.java @@ -24,17 +24,15 @@ /** * @test * @bug 6270015 + * @run main/othervm Test1 * @summary Light weight HTTP server */ import com.sun.net.httpserver.*; -import java.util.*; import java.util.concurrent.*; import java.io.*; import java.net.*; -import java.security.*; -import java.security.cert.*; import javax.net.ssl.*; /* basic http/s connectivity test diff --git a/jdk/test/com/sun/net/httpserver/Test11.java b/jdk/test/com/sun/net/httpserver/Test11.java index d3db077416f..f683a16e834 100644 --- a/jdk/test/com/sun/net/httpserver/Test11.java +++ b/jdk/test/com/sun/net/httpserver/Test11.java @@ -28,7 +28,6 @@ */ import java.net.*; -import java.util.*; import java.util.concurrent.*; import java.io.*; import com.sun.net.httpserver.*; @@ -52,22 +51,25 @@ public class Test11 { public static void main (String[] args) throws Exception { System.out.print ("Test 11: "); - HttpServer server = HttpServer.create (new InetSocketAddress(0), 0); - HttpContext ctx = server.createContext ( - "/foo/bar/", new Handler () - ); - ExecutorService s = Executors.newCachedThreadPool(); - server.setExecutor (s); - server.start (); - URL url = new URL ("http://localhost:" + server.getAddress().getPort()+ - "/Foo/bar/test.html"); - HttpURLConnection urlc = (HttpURLConnection)url.openConnection(); - int r = urlc.getResponseCode(); - System.out.println ("OK"); - s.shutdown(); - server.stop(5); - if (r == 200) { - throw new RuntimeException ("wrong response received"); + HttpServer server = HttpServer.create(new InetSocketAddress(0), 0); + ExecutorService s = Executors.newCachedThreadPool(); + try { + HttpContext ctx = server.createContext ( + "/foo/bar/", new Handler () + ); + s = Executors.newCachedThreadPool(); + server.start (); + URL url = new URL ("http://localhost:" + server.getAddress().getPort()+ + "/Foo/bar/test.html"); + HttpURLConnection urlc = (HttpURLConnection)url.openConnection(); + int r = urlc.getResponseCode(); + if (r == 200) { + throw new RuntimeException ("wrong response received"); + } + System.out.println ("OK"); + } finally { + s.shutdown(); + server.stop(2); } } } diff --git a/jdk/test/com/sun/net/httpserver/Test12.java b/jdk/test/com/sun/net/httpserver/Test12.java index d7dd0d931f5..6d9049697a7 100644 --- a/jdk/test/com/sun/net/httpserver/Test12.java +++ b/jdk/test/com/sun/net/httpserver/Test12.java @@ -24,17 +24,15 @@ /** * @test * @bug 6270015 + * @run main/othervm Test12 * @summary Light weight HTTP server */ import com.sun.net.httpserver.*; -import java.util.*; import java.util.concurrent.*; import java.io.*; import java.net.*; -import java.security.*; -import java.security.cert.*; import javax.net.ssl.*; /* basic http/s connectivity test diff --git a/jdk/test/com/sun/net/httpserver/Test13.java b/jdk/test/com/sun/net/httpserver/Test13.java index f990885f294..a4299322038 100644 --- a/jdk/test/com/sun/net/httpserver/Test13.java +++ b/jdk/test/com/sun/net/httpserver/Test13.java @@ -24,17 +24,16 @@ /** * @test * @bug 6270015 + * @run main/othervm Test13 * @summary Light weight HTTP server */ import com.sun.net.httpserver.*; -import java.util.*; import java.util.concurrent.*; import java.io.*; import java.net.*; -import java.security.*; -import java.security.cert.*; + import javax.net.ssl.*; /* basic http/s connectivity test diff --git a/jdk/test/com/sun/net/httpserver/Test6a.java b/jdk/test/com/sun/net/httpserver/Test6a.java index d22db274f3a..0367fa76da6 100644 --- a/jdk/test/com/sun/net/httpserver/Test6a.java +++ b/jdk/test/com/sun/net/httpserver/Test6a.java @@ -24,17 +24,15 @@ /** * @test * @bug 6270015 + * @run main/othervm Test6a * @summary Light weight HTTP server */ import com.sun.net.httpserver.*; -import java.util.*; import java.util.concurrent.*; import java.io.*; import java.net.*; -import java.security.*; -import javax.security.auth.callback.*; import javax.net.ssl.*; /** diff --git a/jdk/test/com/sun/net/httpserver/Test7a.java b/jdk/test/com/sun/net/httpserver/Test7a.java index 3080b807334..67039f81da0 100644 --- a/jdk/test/com/sun/net/httpserver/Test7a.java +++ b/jdk/test/com/sun/net/httpserver/Test7a.java @@ -24,18 +24,15 @@ /** * @test * @bug 6270015 + * @run main/othervm Test7a * @summary Light weight HTTP server */ import com.sun.net.httpserver.*; -import java.util.*; import java.util.concurrent.*; -import java.util.logging.*; import java.io.*; import java.net.*; -import java.security.*; -import javax.security.auth.callback.*; import javax.net.ssl.*; /** diff --git a/jdk/test/com/sun/net/httpserver/Test8a.java b/jdk/test/com/sun/net/httpserver/Test8a.java index ed64d1a4621..9e8f96a9728 100644 --- a/jdk/test/com/sun/net/httpserver/Test8a.java +++ b/jdk/test/com/sun/net/httpserver/Test8a.java @@ -24,18 +24,15 @@ /** * @test * @bug 6270015 + * @run main/othervm Test8a * @summary Light weight HTTP server */ import com.sun.net.httpserver.*; -import java.util.*; import java.util.concurrent.*; -import java.util.logging.*; import java.io.*; import java.net.*; -import java.security.*; -import javax.security.auth.callback.*; import javax.net.ssl.*; /** @@ -50,46 +47,50 @@ public class Test8a extends Test { //h.setLevel (Level.INFO); //log.addHandler (h); //log.setLevel (Level.INFO); - Handler handler = new Handler(); - InetSocketAddress addr = new InetSocketAddress (0); - HttpsServer server = HttpsServer.create (addr, 0); - HttpContext ctx = server.createContext ("/test", handler); - ExecutorService executor = Executors.newCachedThreadPool(); - SSLContext ssl = new SimpleSSLContext(System.getProperty("test.src")).get(); - server.setHttpsConfigurator(new HttpsConfigurator (ssl)); - server.setExecutor (executor); - server.start (); + HttpsServer server = null; + ExecutorService executor = null; + try { + Handler handler = new Handler(); + InetSocketAddress addr = new InetSocketAddress (0); + server = HttpsServer.create (addr, 0); + HttpContext ctx = server.createContext ("/test", handler); + executor = Executors.newCachedThreadPool(); + SSLContext ssl = new SimpleSSLContext(System.getProperty("test.src")).get(); + server.setHttpsConfigurator(new HttpsConfigurator (ssl)); + server.setExecutor (executor); + server.start (); - URL url = new URL ("https://localhost:"+server.getAddress().getPort()+"/test/foo.html"); - System.out.print ("Test8a: " ); - HttpsURLConnection urlc = (HttpsURLConnection)url.openConnection (); - urlc.setDoOutput (true); - urlc.setRequestMethod ("POST"); - urlc.setHostnameVerifier (new DummyVerifier()); - urlc.setSSLSocketFactory (ssl.getSocketFactory()); - OutputStream os = new BufferedOutputStream (urlc.getOutputStream(), 8000); - for (int i=0; i>)ois.readObject(); } catch (Exception ex) { @@ -206,6 +224,8 @@ static class NameVerifier implements HostnameVerifier { try { File file = new File(filename); fos = new FileOutputStream(file); + streams.add(fos); + files.add(file); ObjectOutputStream oos = new ObjectOutputStream(fos); oos.writeObject(rspHeaders); } catch (Exception ex) { diff --git a/jdk/test/java/net/ResponseCache/getResponseCode.java b/jdk/test/java/net/ResponseCache/getResponseCode.java index 02f0f565d28..b5a4d0c2e04 100644 --- a/jdk/test/java/net/ResponseCache/getResponseCode.java +++ b/jdk/test/java/net/ResponseCache/getResponseCode.java @@ -39,6 +39,7 @@ import java.io.*; public class getResponseCode { static URL url; static String FNPrefix; + static List resources = new ArrayList<>(); getResponseCode() throws Exception { url = new URL("http://localhost/file1.cache"); @@ -57,6 +58,9 @@ public class getResponseCode { new getResponseCode(); } finally{ ResponseCache.setDefault(null); + for (Closeable c : resources) { + try { c.close(); } catch (IOException unused) {} + } } } @@ -77,6 +81,7 @@ public class getResponseCode { public MyResponse(String filename) { try { fis = new FileInputStream(new File(filename)); + resources.add(fis); headers = (Map>)new ObjectInputStream(fis).readObject(); } catch (Exception ex) { throw new RuntimeException(ex.getMessage()); diff --git a/jdk/test/java/net/Socket/AccurateTimeout.java b/jdk/test/java/net/Socket/AccurateTimeout.java deleted file mode 100644 index 81a664d31b3..00000000000 --- a/jdk/test/java/net/Socket/AccurateTimeout.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. - * 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 4512028 - * @summary Check the tolerance on read timeouts. - */ -import java.net.*; -import java.io.*; - -public class AccurateTimeout { - - static final int TOLERANCE = 100; - - static boolean skipTest() { - String os = System.getProperty("os.name"); - if (os.equals("Windows 95") || - os.equals("Windows 98") || - os.equals("Windows Me")) { - - System.out.println("Due to an OS bug timeout tolerance cannot be tested on this OS"); - return true; - } - return false; - } - - public static void main(String args[]) throws Exception { - - if (skipTest()) { - return; - } - - int failures = 0; - int timeout; - - System.out.println(""); - System.out.println("Testing Socket.getInputStream().read() ..."); - System.out.println(""); - - ServerSocket ss = new ServerSocket(0); - Socket s1 = new Socket(InetAddress.getLocalHost(), ss.getLocalPort()); - Socket s2 = ss.accept(); - - InputStream in = s1.getInputStream(); - - timeout = 100; - while (timeout < 2500) { - s1.setSoTimeout(timeout); - - long startTime = System.currentTimeMillis(); - try { - in.read(); - } catch (SocketTimeoutException e) { - } - long actual = System.currentTimeMillis() - startTime; - - System.out.print("excepted: " + timeout + " actual: " + actual); - - if (Math.abs(actual-timeout) > TOLERANCE) { - System.out.print(" *** FAIL: outside tolerance"); - failures++; - } else { - System.out.print(" PASS."); - } - - System.out.println(""); - timeout += 200; - } - - s1.close(); - s2.close(); - ss.close(); - - - // ---------- - - - System.out.println(""); - System.out.println("Testing DatagramSocket.receive ..."); - System.out.println(""); - - byte b[] = new byte[8]; - DatagramPacket p = new DatagramPacket(b, b.length); - - DatagramSocket ds = new DatagramSocket(); - - timeout = 100; - while (timeout < 2500) { - ds.setSoTimeout(timeout); - - long startTime = System.currentTimeMillis(); - try { - ds.receive(p); - } catch (SocketTimeoutException e) { - } - long actual = System.currentTimeMillis() - startTime; - - System.out.print("excepted: " + timeout + " actual: " + actual); - - if (Math.abs(actual-timeout) > TOLERANCE) { - System.out.print(" *** FAIL: outside tolerance"); - failures++; - } else { - System.out.print(" PASS."); - } - - System.out.println(""); - timeout += 200; - } - - ds.close(); - - System.out.println(""); - - // --------- - - if (failures > 0) { - throw new Exception("Test failed: " + failures + - " test(s) outside tolerance"); - } - - } - -} diff --git a/jdk/test/java/net/Socket/CloseAvailable.java b/jdk/test/java/net/Socket/CloseAvailable.java index d7f20828098..5e9fd5c97b3 100644 --- a/jdk/test/java/net/Socket/CloseAvailable.java +++ b/jdk/test/java/net/Socket/CloseAvailable.java @@ -47,6 +47,7 @@ public class CloseAvailable implements Runnable { t.start(); Socket soc = ss.accept(); + ss.close(); DataInputStream is = new DataInputStream(soc.getInputStream()); is.close(); @@ -64,7 +65,7 @@ public class CloseAvailable implements Runnable { public void run() { try { Socket s = new Socket(addr, port); - + s.close(); } catch (Exception e) { e.printStackTrace(); } diff --git a/jdk/test/java/net/Socket/DeadlockTest.java b/jdk/test/java/net/Socket/DeadlockTest.java index ff601c71936..a5d7751f5fd 100644 --- a/jdk/test/java/net/Socket/DeadlockTest.java +++ b/jdk/test/java/net/Socket/DeadlockTest.java @@ -33,29 +33,32 @@ import java.io.*; public class DeadlockTest { public static void main(String [] argv) throws Exception { + ServerSocket ss = new ServerSocket(0); + Socket clientSocket = new Socket(); - // Start the server thread - Thread s1 = new Thread(new ServerThread()); - s1.start(); + try { + // Start the server thread + Thread s1 = new Thread(new ServerThread(ss)); + s1.start(); - // Sleep to make sure s1 has created a server socket - Thread.sleep(1000); + // Start the client thread + ClientThread ct = new ClientThread(clientSocket, ss.getLocalPort()); + Thread c1 = new Thread(ct); + c1.start(); - // Start the client thread - ClientThread ct = new ClientThread(); - Thread c1 = new Thread(ct); - c1.start(); + // Wait for the client thread to finish + c1.join(20000); - // Wait for the client thread to finish - c1.join(40000); - - // If timeout, we assume there is a deadlock - if (c1.isAlive() == true) { - // Close the socket to force the server thread - // terminate too - s1.stop(); - ct.getSock().close(); - throw new Exception("Takes too long. Dead lock"); + // If timeout, we assume there is a deadlock + if (c1.isAlive() == true) { + // Close the socket to force the server thread + // terminate too + s1.stop(); + throw new Exception("Takes too long. Dead lock"); + } + } finally { + ss.close(); + clientSocket.close(); } } } @@ -71,8 +74,8 @@ class ServerThread implements Runnable { Socket sock; - public ServerThread() throws Exception { - + public ServerThread(ServerSocket serverSocket) throws Exception { + this.server = serverSocket; } public void ping(int cnt) { @@ -85,7 +88,6 @@ class ServerThread implements Runnable { try { if (Thread.currentThread().getName().startsWith("child") == false) { - server = new ServerSocket(4711); sock = server.accept(); new Thread(this, "child").start(); @@ -107,6 +109,7 @@ class ServerThread implements Runnable { } } catch (Throwable e) { + System.out.println(e); // If anything goes wrong, just quit. } @@ -141,10 +144,11 @@ class ClientThread implements Runnable { Socket sock; - public ClientThread() throws Exception { + public ClientThread(Socket sock, int serverPort) throws Exception { try { - System.out.println("About to create a socket"); - sock = new Socket(InetAddress.getLocalHost().getHostName(), 4711); + System.out.println("About to connect the client socket"); + this.sock = sock; + this.sock.connect(new InetSocketAddress("localhost", serverPort)); System.out.println("connected"); out = new ObjectOutputStream(sock.getOutputStream()); @@ -156,10 +160,6 @@ class ClientThread implements Runnable { } } - public Socket getSock() { - return sock; - } - private int cnt = 1; public void run() { @@ -213,6 +213,7 @@ class Message implements java.io.Serializable { System.out.println("write message done " + cnt++); } catch (IOException ioe) { // Ignore the exception + System.out.println(ioe); } } } diff --git a/jdk/test/java/net/Socket/LingerTest.java b/jdk/test/java/net/Socket/LingerTest.java index 600dbd7db40..c84e153116b 100644 --- a/jdk/test/java/net/Socket/LingerTest.java +++ b/jdk/test/java/net/Socket/LingerTest.java @@ -81,7 +81,7 @@ public class LingerTest { public void run() { System.out.println ("Another starts"); try { - Thread.currentThread().sleep(delay); + Thread.sleep(delay); Socket s = new Socket("localhost", port); synchronized (this) { connected = true; @@ -105,7 +105,6 @@ public class LingerTest { Socket s1 = new Socket("localhost", ss.getLocalPort()); Socket s2 = ss.accept(); - // setup conditions for untransmitted data and lengthy // linger interval s1.setSendBufferSize(128*1024); @@ -122,14 +121,15 @@ public class LingerTest { thr.start(); // give sender time to queue the data - Thread.currentThread().sleep(1000); + Thread.sleep(1000); // close the socket asynchronously (new Thread(new Closer(s1))).start(); // give another time to run - Thread.currentThread().sleep(10000); + Thread.sleep(10000); + ss.close(); // check that another is done if (!another.connected()) { throw new RuntimeException("Another thread is blocked"); diff --git a/jdk/test/java/net/Socket/LinkLocal.java b/jdk/test/java/net/Socket/LinkLocal.java index 1d3288bdcf1..8a0aea287b0 100644 --- a/jdk/test/java/net/Socket/LinkLocal.java +++ b/jdk/test/java/net/Socket/LinkLocal.java @@ -58,11 +58,10 @@ public class LinkLocal { } catch (SocketException e) { failed++; System.out.println("Test failed: " + e); + } finally { + s.close(); + ss.close(); } - - // clean up - s.close(); - ss.close(); } static void UdpTest(InetAddress ia, boolean connected) throws Exception { @@ -93,16 +92,16 @@ public class LinkLocal { ds1.send(p); System.out.println("Packet has been sent."); - ds2.setSoTimeout(1000); + ds2.setSoTimeout(5000); ds2.receive(p); System.out.println("Test passed - packet received."); } catch (SocketException e) { failed++; System.out.println("Test failed: " + e); + } finally { + ds1.close(); + ds2.close(); } - - ds1.close(); - ds2.close(); } static void TestAddress(InetAddress ia) throws Exception { @@ -138,6 +137,9 @@ public class LinkLocal { Enumeration nifs = NetworkInterface.getNetworkInterfaces(); while (nifs.hasMoreElements()) { NetworkInterface ni = (NetworkInterface)nifs.nextElement(); + if (!ni.isUp()) + continue; + Enumeration addrs = ni.getInetAddresses(); while (addrs.hasMoreElements()) { InetAddress addr = (InetAddress)addrs.nextElement(); diff --git a/jdk/test/java/net/Socket/ProxyCons.java b/jdk/test/java/net/Socket/ProxyCons.java index 901638ec280..da80337070d 100644 --- a/jdk/test/java/net/Socket/ProxyCons.java +++ b/jdk/test/java/net/Socket/ProxyCons.java @@ -39,6 +39,7 @@ public class ProxyCons { public void run () { try { Socket s = server.accept (); + s.close(); while (!finished ()) { Thread.sleep (500); } @@ -58,10 +59,9 @@ public class ProxyCons { public ProxyCons() { } - void test() { + void test() throws Exception { + ServerSocket ss = new ServerSocket(0); try { - ServerSocket ss = new ServerSocket(); - ss.bind(new InetSocketAddress(0)); Server s = new Server(ss); s.start(); Socket sock = new Socket(Proxy.NO_PROXY); @@ -70,10 +70,12 @@ public class ProxyCons { sock.close(); } catch (java.io.IOException e) { throw new RuntimeException(e); + } finally { + ss.close(); } } - public static void main(String[] args) { + public static void main(String[] args) throws Exception { ProxyCons c = new ProxyCons(); c.test(); } diff --git a/jdk/test/java/net/Socket/ReadTimeout.java b/jdk/test/java/net/Socket/ReadTimeout.java index 26097827efb..89fe4150466 100644 --- a/jdk/test/java/net/Socket/ReadTimeout.java +++ b/jdk/test/java/net/Socket/ReadTimeout.java @@ -44,7 +44,7 @@ public class ReadTimeout { sin = InetAddress.getLocalHost(); srv = new ServerSocket(port); port = srv.getLocalPort(); - soc = new Socket(sin, port, true); + soc = new Socket(sin, port); soc1 = srv.accept(); soc.setSoTimeout(tout); @@ -53,10 +53,10 @@ public class ReadTimeout { os = soc1.getOutputStream(); is.read(); } catch(InterruptedIOException e) { + } finally { + soc.close(); + soc1.close(); + srv.close(); } - - soc.close(); - soc1.close(); - srv.close(); } } diff --git a/jdk/test/java/net/Socket/SetReceiveBufferSize.java b/jdk/test/java/net/Socket/SetReceiveBufferSize.java index 562010d48ef..fa5302a4882 100644 --- a/jdk/test/java/net/Socket/SetReceiveBufferSize.java +++ b/jdk/test/java/net/Socket/SetReceiveBufferSize.java @@ -32,29 +32,14 @@ import java.net.Socket; import java.net.ServerSocket; public class SetReceiveBufferSize { - class Server extends Thread { - private ServerSocket ss; - public Server(ServerSocket ss) { - this.ss = ss; - } - - public void run() { - try { - ss.accept(); - } catch (Exception e) { - } - } - } - public static void main(String[] args) throws Exception { SetReceiveBufferSize s = new SetReceiveBufferSize(); } public SetReceiveBufferSize() throws Exception { ServerSocket ss = new ServerSocket(0); - Server serv = new Server(ss); - serv.start(); Socket s = new Socket("localhost", ss.getLocalPort()); + Socket accepted = ss.accept(); try { s.setReceiveBufferSize(0); } catch (IllegalArgumentException e) { @@ -62,6 +47,8 @@ public class SetReceiveBufferSize { } catch (Exception ex) { } finally { ss.close(); + s.close(); + accepted.close(); } throw new RuntimeException("IllegalArgumentException not thrown!"); } diff --git a/jdk/test/java/net/Socket/SetSoLinger.java b/jdk/test/java/net/Socket/SetSoLinger.java index 97351f35212..f2eaff43823 100644 --- a/jdk/test/java/net/Socket/SetSoLinger.java +++ b/jdk/test/java/net/Socket/SetSoLinger.java @@ -30,36 +30,24 @@ import java.net.*; -public class SetSoLinger implements Runnable { - static ServerSocket ss; - static InetAddress addr; - static int port; +public class SetSoLinger { + static final int LINGER = 65546; public static void main(String args[]) throws Exception { - boolean error = true; - int linger = 65546; - int value = 0; - addr = InetAddress.getLocalHost(); - ss = new ServerSocket(0); - port = ss.getLocalPort(); + int value; + InetAddress addr = InetAddress.getLocalHost(); + ServerSocket ss = new ServerSocket(0); + int port = ss.getLocalPort(); - Thread t = new Thread(new SetSoLinger()); - t.start(); + Socket s = new Socket(addr, port); Socket soc = ss.accept(); - soc.setSoLinger(true, linger); + soc.setSoLinger(true, LINGER); value = soc.getSoLinger(); soc.close(); + s.close(); + ss.close(); if(value != 65535) throw new RuntimeException("Failed. Value not properly reduced."); } - - public void run() { - try { - Socket s = new Socket(addr, port); - } catch (Exception e) { - e.printStackTrace(); - } - } - } diff --git a/jdk/test/java/net/Socket/ShutdownBoth.java b/jdk/test/java/net/Socket/ShutdownBoth.java index bf19924e051..99281c76e1a 100644 --- a/jdk/test/java/net/Socket/ShutdownBoth.java +++ b/jdk/test/java/net/Socket/ShutdownBoth.java @@ -36,12 +36,14 @@ public class ShutdownBoth { Socket s1 = new Socket(ss.getInetAddress(), ss.getLocalPort()); Socket s2 = ss.accept(); - s1.shutdownInput(); - s1.shutdownOutput(); // failed b55 - - s1.close(); - s2.close(); - ss.close(); + try { + s1.shutdownInput(); + s1.shutdownOutput(); // failed b55 + } finally { + s1.close(); + s2.close(); + ss.close(); + } } } diff --git a/jdk/test/java/net/Socket/SoTimeout.java b/jdk/test/java/net/Socket/SoTimeout.java index 1273d968c12..0b1e448523d 100644 --- a/jdk/test/java/net/Socket/SoTimeout.java +++ b/jdk/test/java/net/Socket/SoTimeout.java @@ -52,9 +52,10 @@ public class SoTimeout implements Runnable { t.start(); Socket s = serverSocket.accept(); + serverSocket.close(); - // set a 1 second timeout on the socket - s.setSoTimeout(1000); + // set a 5 second timeout on the socket + s.setSoTimeout(5000); s.getInputStream().read(b, 0, b.length); s.close(); @@ -64,7 +65,7 @@ public class SoTimeout implements Runnable { // this sequence should complete fairly quickly and if it // takes something resembling the the SoTimeout value then // we are probably incorrectly blocking and not waking up - if (waited > 500) { + if (waited > 2000) { throw new Exception("shouldn't take " + waited + " to complete"); } } diff --git a/jdk/test/java/net/Socket/Timeout.java b/jdk/test/java/net/Socket/Timeout.java index 653db8f726a..31471acfc1a 100644 --- a/jdk/test/java/net/Socket/Timeout.java +++ b/jdk/test/java/net/Socket/Timeout.java @@ -31,18 +31,16 @@ import java.net.*; import java.io.*; public class Timeout { - - public static ServerSocket sock; - public static void main(String[] args) throws Exception { boolean success = false; + ServerSocket sock = new ServerSocket(0); try { - ServerSocket sock; - sock = new ServerSocket(2333); sock.setSoTimeout(2); sock.accept(); } catch (InterruptedIOException e) { success = true; + } finally { + sock.close(); } if (!success) throw new RuntimeException("Socket timeout failure."); diff --git a/jdk/test/java/net/Socket/UrgentDataTest.java b/jdk/test/java/net/Socket/UrgentDataTest.java index 7b6a8dca187..d63bc5cb805 100644 --- a/jdk/test/java/net/Socket/UrgentDataTest.java +++ b/jdk/test/java/net/Socket/UrgentDataTest.java @@ -90,63 +90,64 @@ public class UrgentDataTest { } public void run () throws Exception { - if (isClient) { - client = new Socket (clHost, clPort); - clis = client.getInputStream(); - clos = client.getOutputStream(); - client.setOOBInline (true); - if (client.getOOBInline() != true) { - throw new RuntimeException ("Setting OOBINLINE failed"); - } - } - if (isServer) { - server = listener.accept (); - sis = server.getInputStream(); - sos = server.getOutputStream(); - } - if (isClient) { - clos.write ("Hello".getBytes ()); - client.sendUrgentData (100); - clos.write ("world".getBytes ()); - } - // read Hello world from server (during which oob byte must have been dropped) - String s = "Helloworld"; - if (isServer) { - for (int y=0; y= 0) { throw ioe; } + } finally { + server.close(); } - server.close(); } } diff --git a/jdk/test/java/net/Socket/setReuseAddress/Restart.java b/jdk/test/java/net/Socket/setReuseAddress/Restart.java index 90c2a1810d2..08bb5af2f62 100644 --- a/jdk/test/java/net/Socket/setReuseAddress/Restart.java +++ b/jdk/test/java/net/Socket/setReuseAddress/Restart.java @@ -39,27 +39,28 @@ public class Restart { */ public static void main(String args[]) throws Exception { + ServerSocket ss = new ServerSocket(0); + Socket s1 = null, s2 = null; + try { + int port = ss.getLocalPort(); - InetSocketAddress isa = new InetSocketAddress(0); - ServerSocket ss = new ServerSocket(); - ss.bind(isa); + s1 = new Socket(InetAddress.getLocalHost(), port); + s2 = ss.accept(); - int port = ss.getLocalPort(); + // close server socket and the accepted connection + ss.close(); + s2.close(); - Socket s1 = new Socket(InetAddress.getLocalHost(), port); - Socket s2 = ss.accept(); + ss = new ServerSocket(); + ss.bind( new InetSocketAddress(port) ); + ss.close(); - // close server socket and the accepted connection - ss.close(); - s2.close(); - - boolean failed = false; - - ss = new ServerSocket(); - ss.bind( new InetSocketAddress(port) ); - ss.close(); - - // close the client socket - s1.close(); + // close the client socket + s1.close(); + } finally { + if (ss != null) ss.close(); + if (s1 != null) s1.close(); + if (s2 != null) s2.close(); + } } } diff --git a/jdk/test/java/net/SocketInputStream/SocketClosedException.java b/jdk/test/java/net/SocketInputStream/SocketClosedException.java index b116cd21d0b..cf141863a53 100644 --- a/jdk/test/java/net/SocketInputStream/SocketClosedException.java +++ b/jdk/test/java/net/SocketInputStream/SocketClosedException.java @@ -32,68 +32,37 @@ import java.io.*; import java.net.*; public class SocketClosedException { - - /* - * Is the server ready to serve? - */ - volatile static boolean serverReady = false; - - /* - * Define the server side of the test. - * - * If the server prematurely exits, serverReady will be set to true - * to avoid infinite hangs. - */ static void doServerSide() throws Exception { - ServerSocket serverSocket = new ServerSocket(serverPort); - serverPort = serverSocket.getLocalPort(); + try { + Socket socket = serverSocket.accept(); - /* - * Signal Client, we're ready for a connect. - */ - serverReady = true; + OutputStream os = socket.getOutputStream(); - Socket socket = serverSocket.accept(); - - InputStream is = socket.getInputStream(); - OutputStream os = socket.getOutputStream(); - - os.write(85); - os.flush(); - socket.close(); - } - - /* - * Define the client side of the test. - * - * If the server prematurely exits, serverReady will be set to true - * to avoid infinite hangs. - */ - static void doClientSide() throws Exception { - - /* - * Wait for server to get started. - */ - while (!serverReady) { - Thread.sleep(5000); + os.write(85); + os.flush(); + socket.close(); + } finally { + serverSocket.close(); } - - Socket socket = new Socket("localhost", serverPort); - InputStream is = socket.getInputStream(); - OutputStream os = socket.getOutputStream(); - - int read = is.read(); - socket.close(); - read = is.read(); } - static int serverPort = 0; + static void doClientSide(int port) throws Exception { + Socket socket = new Socket("localhost", port); + InputStream is = socket.getInputStream(); + + is.read(); + socket.close(); + is.read(); + } + + static ServerSocket serverSocket; static Exception serverException = null; public static void main(String[] args) throws Exception { + serverSocket = new ServerSocket(0); startServer(); try { - doClientSide(); + doClientSide(serverSocket.getLocalPort()); } catch (SocketException e) { if (!e.getMessage().equalsIgnoreCase("Socket closed")) { throw new Exception("Received a wrong exception message: " + @@ -108,21 +77,14 @@ public class SocketClosedException { } static void startServer() { - Thread serverThread = new Thread() { + (new Thread() { public void run() { try { doServerSide(); } catch (Exception e) { - /* - * server thread just died. - * Release the client, if not active already... - */ - System.err.println("Server died..."); - serverReady = true; - serverException = e; + e.printStackTrace(); } } - }; - serverThread.start(); + }).start(); } } diff --git a/jdk/test/java/net/SocketInputStream/SocketTimeout.java b/jdk/test/java/net/SocketInputStream/SocketTimeout.java index 37d84162fa7..ad4c70acbbf 100644 --- a/jdk/test/java/net/SocketInputStream/SocketTimeout.java +++ b/jdk/test/java/net/SocketInputStream/SocketTimeout.java @@ -31,26 +31,24 @@ import java.net.*; import java.io.*; public class SocketTimeout { + static final int TIMEOUT = 1000; + public static void main(String args[]) throws Exception { - InetAddress sin = null; + InetAddress sin = InetAddress.getLocalHost(); Socket soc = null,soc1 = null; InputStream is = null; - OutputStream os = null; ServerSocket srv = null; int port = 0; - int tout = 1000; - sin = InetAddress.getLocalHost(); - srv = new ServerSocket(port); + srv = new ServerSocket(0); port = srv.getLocalPort(); soc = new Socket(sin, port); soc1 = srv.accept(); - soc.setSoTimeout(tout); - srv.setSoTimeout(tout); + soc.setSoTimeout(TIMEOUT); + srv.setSoTimeout(TIMEOUT); try { is = soc.getInputStream(); - os = soc1.getOutputStream(); is.read(); } catch(InterruptedIOException e) { try { @@ -59,6 +57,9 @@ public class SocketTimeout { } catch(NoClassDefFoundError e1) { throw new Exception ("SocketTimeoutException: not found"); } + } finally { + soc.close(); + soc1.close(); } // now check accept @@ -72,12 +73,14 @@ public class SocketTimeout { } catch(NoClassDefFoundError e1) { throw new Exception ("SocketTimeoutException: not found"); } + } finally { + srv.close(); } // Now check DatagramSocket.receive() DatagramSocket dg = new DatagramSocket (); - dg.setSoTimeout (tout); + dg.setSoTimeout (TIMEOUT); try { dg.receive (new DatagramPacket (new byte [64], 64)); @@ -88,11 +91,8 @@ public class SocketTimeout { } catch(NoClassDefFoundError e1) { throw new Exception ("SocketTimeoutException: not found"); } + } finally { + dg.close(); } - - soc.close(); - soc1.close(); - srv.close(); - dg.close(); } } diff --git a/jdk/test/java/net/URL/GetContent.java b/jdk/test/java/net/URL/GetContent.java index b913cfe0779..aa32da29bd3 100644 --- a/jdk/test/java/net/URL/GetContent.java +++ b/jdk/test/java/net/URL/GetContent.java @@ -53,11 +53,13 @@ public class GetContent implements Runnable { // wait for client to read response - otherwise http // client get error and re-establish connection - Thread.currentThread().sleep(2000); + Thread.sleep(2000); s.close(); } catch (Exception e) { e.printStackTrace(); + } finally { + try { ss.close(); } catch (IOException unused) {} } } @@ -81,8 +83,6 @@ public class GetContent implements Runnable { error = false; } - ss.close(); - if (error) throw new RuntimeException("No IOException generated."); } diff --git a/jdk/test/java/net/URLClassLoader/ClassLoad.java b/jdk/test/java/net/URLClassLoader/ClassLoad.java index b9aa687b4cc..c23073f93bf 100644 --- a/jdk/test/java/net/URLClassLoader/ClassLoad.java +++ b/jdk/test/java/net/URLClassLoader/ClassLoad.java @@ -27,20 +27,45 @@ * @summary Test for FileNotFoundException when loading bogus class */ -import java.net.*; -import java.io.*; +import java.io.InputStream; +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.URL; +import java.net.URLClassLoader; +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpServer; public class ClassLoad { public static void main(String[] args) throws Exception { boolean error = true; + + // Start a dummy server to return 404 + HttpServer server = HttpServer.create(new InetSocketAddress(0), 0); + HttpHandler handler = new HttpHandler() { + public void handle(HttpExchange t) throws IOException { + InputStream is = t.getRequestBody(); + while (is.read() != -1); + t.sendResponseHeaders (404, -1); + t.close(); + } + }; + server.createContext("/", handler); + server.start(); + + // Client request try { - URL url = new URL(args.length >= 1 ? args[0] : "http://jini.east/"); + URL url = new URL("http://localhost:" + server.getAddress().getPort()); String name = args.length >= 2 ? args[1] : "foo.bar.Baz"; ClassLoader loader = new URLClassLoader(new URL[] { url }); + System.out.println(url); Class c = loader.loadClass(name); System.out.println("Loaded class \"" + c.getName() + "\"."); } catch (ClassNotFoundException ex) { + System.out.println(ex); error = false; + } finally { + server.stop(0); } if (error) throw new RuntimeException("No ClassNotFoundException generated"); diff --git a/jdk/test/java/net/URLConnection/DisconnectAfterEOF.java b/jdk/test/java/net/URLConnection/DisconnectAfterEOF.java index 927fedfd91d..0a3814794b7 100644 --- a/jdk/test/java/net/URLConnection/DisconnectAfterEOF.java +++ b/jdk/test/java/net/URLConnection/DisconnectAfterEOF.java @@ -56,7 +56,6 @@ public class DisconnectAfterEOF { int cl = -1; int remaining = -1; StringBuffer sb = new StringBuffer(); - Random r = new Random(); boolean close = false; boolean inBody = false; @@ -239,8 +238,6 @@ public class DisconnectAfterEOF { } public static void main(String args[]) throws Exception { - Random r = new Random(); - // start server ServerSocket ss = new ServerSocket(0); Server svr = new Server(ss); @@ -273,7 +270,7 @@ public class DisconnectAfterEOF { URLConnection uc1 = doRequest(uri); doResponse(uc1); - Thread.currentThread().sleep(2000); + Thread.sleep(2000); URLConnection uc2 = doRequest(uri); diff --git a/jdk/test/java/net/URLConnection/HandleContentTypeWithAttrs.java b/jdk/test/java/net/URLConnection/HandleContentTypeWithAttrs.java index 3cad25dbe0c..50fcd388f16 100644 --- a/jdk/test/java/net/URLConnection/HandleContentTypeWithAttrs.java +++ b/jdk/test/java/net/URLConnection/HandleContentTypeWithAttrs.java @@ -111,9 +111,8 @@ class myHttpServer implements Runnable, Cloneable { } catch(Exception e) { System.out.print("Server failure\n"); e.printStackTrace(); - try { - serverSocket.close(); - } catch(IOException e2) {} + } finally { + try { serverSocket.close(); } catch(IOException unused) {} } } else { try { @@ -127,10 +126,9 @@ class myHttpServer implements Runnable, Cloneable { } catch(Exception e) { // System.out.print("Service handler failure\n"); // e.printStackTrace(); + } finally { + try { close(); } catch(IOException unused) {} } - try { - close(); - } catch(IOException e2) {} } } diff --git a/jdk/test/java/net/URLConnection/HttpContinueStackOverflow.java b/jdk/test/java/net/URLConnection/HttpContinueStackOverflow.java index 8d9aab013ff..502adf9fae4 100644 --- a/jdk/test/java/net/URLConnection/HttpContinueStackOverflow.java +++ b/jdk/test/java/net/URLConnection/HttpContinueStackOverflow.java @@ -30,7 +30,7 @@ */ import java.io.BufferedReader; import java.io.InputStreamReader; -import java.io.OutputStreamWriter; +import java.io.IOException; import java.io.PrintStream; import java.net.ServerSocket; import java.net.Socket; @@ -41,61 +41,56 @@ public class HttpContinueStackOverflow { static class Server implements Runnable { int port; + ServerSocket serverSock ; - Server(int port) { - this.port = port; + Server() throws IOException { + serverSock = new ServerSocket(0); + } + + int getLocalPort() { + return serverSock.getLocalPort(); } public void run() { + Socket sock = null; try { - /* bind to port and wait for connection */ - ServerSocket serverSock = new ServerSocket( port ); serverSock.setSoTimeout(10000); - Socket sock = serverSock.accept(); + sock = serverSock.accept(); /* setup streams and read http request */ BufferedReader in = new BufferedReader( new InputStreamReader(sock.getInputStream())); PrintStream out = new PrintStream( sock.getOutputStream() ); - String request = in.readLine(); + in.readLine(); /* send continue followed by invalid response */ out.println("HTTP/1.1 100 Continue\r"); out.println("\r"); out.println("junk junk junk"); out.flush(); - - sock.close(); } catch (Exception e) { e.printStackTrace(); + } finally { + try { serverSock.close(); } catch (IOException unused) {} + try { sock.close(); } catch (IOException unused) {} } } } - HttpContinueStackOverflow(int port) throws Exception { + HttpContinueStackOverflow() throws Exception { /* create the server */ - Server s = new Server(port); - Thread thr = new Thread(s); - thr.start(); - - /* wait for server to bind to port */ - try { - Thread.currentThread().sleep(2000); - } catch (Exception e) { } + Server s = new Server(); + (new Thread(s)).start(); /* connect to server, connect to server and get response code */ - URL url = new URL("http", "localhost", port, "anything.html"); + URL url = new URL("http", "localhost", s.getLocalPort(), "anything.html"); HttpURLConnection conn = (HttpURLConnection)url.openConnection(); - int respCode = conn.getResponseCode(); + conn.getResponseCode(); System.out.println("TEST PASSED"); } public static void main(String args[]) throws Exception { - int port = 4090; - if (args.length > 0) { - port = Integer.parseInt(args[0]); - } System.out.println("Testing 100-Continue"); - new HttpContinueStackOverflow(port); + new HttpContinueStackOverflow(); } } diff --git a/jdk/test/java/net/URLConnection/Redirect307Test.java b/jdk/test/java/net/URLConnection/Redirect307Test.java index b0a85e14df5..37f044edac1 100644 --- a/jdk/test/java/net/URLConnection/Redirect307Test.java +++ b/jdk/test/java/net/URLConnection/Redirect307Test.java @@ -37,11 +37,11 @@ class RedirServer extends Thread { OutputStream os; int port; - String reply1 = "HTTP/1.1 307 Temporary Redirect\r\n" + + String reply1Part1 = "HTTP/1.1 307 Temporary Redirect\r\n" + "Date: Mon, 15 Jan 2001 12:18:21 GMT\r\n" + "Server: Apache/1.3.14 (Unix)\r\n" + "Location: http://localhost:"; - String reply2 = "/redirected.html\r\n" + + String reply1Part2 = "/redirected.html\r\n" + "Connection: close\r\n" + "Content-Type: text/html; charset=iso-8859-1\r\n\r\n" + "Hello"; @@ -49,9 +49,10 @@ class RedirServer extends Thread { RedirServer (ServerSocket y) { s = y; port = s.getLocalPort(); + System.out.println("Server created listening on " + port); } - String reply3 = "HTTP/1.1 200 Ok\r\n" + + String reply2 = "HTTP/1.1 200 Ok\r\n" + "Date: Mon, 15 Jan 2001 12:18:21 GMT\r\n" + "Server: Apache/1.3.14 (Unix)\r\n" + "Connection: close\r\n" + @@ -64,16 +65,24 @@ class RedirServer extends Thread { is = s1.getInputStream (); os = s1.getOutputStream (); is.read (); - String reply = reply1 + port + reply2; + String reply = reply1Part1 + port + reply1Part2; os.write (reply.getBytes()); + os.close(); /* wait for redirected connection */ s.setSoTimeout (5000); s1 = s.accept (); + is = s1.getInputStream (); os = s1.getOutputStream (); - os.write (reply3.getBytes()); + is.read(); + os.write (reply2.getBytes()); + os.close(); } catch (Exception e) { /* Just need thread to terminate */ + System.out.println("Server: caught " + e); + e.printStackTrace(); + } finally { + try { s.close(); } catch (IOException unused) {} } } }; @@ -84,10 +93,7 @@ public class Redirect307Test { public static final int DELAY = 10; public static void main(String[] args) throws Exception { - int nLoops = 1; - int nSize = 10; - int port, n =0; - byte b[] = new byte[nSize]; + int port; RedirServer server; ServerSocket sock; @@ -119,7 +125,8 @@ public class Redirect307Test { } } catch(IOException e) { - throw new RuntimeException ("Exception caught"); + e.printStackTrace(); + throw new RuntimeException ("Exception caught + " + e); } } } diff --git a/jdk/test/java/net/URLConnection/RedirectLimit.java b/jdk/test/java/net/URLConnection/RedirectLimit.java index 979a938b99c..b0ef22b94d9 100644 --- a/jdk/test/java/net/URLConnection/RedirectLimit.java +++ b/jdk/test/java/net/URLConnection/RedirectLimit.java @@ -76,15 +76,19 @@ class RedirLimitServer extends Thread { is.read (); String reply = reply1 + port + "/redirect" + i + reply2; os.write (reply.getBytes()); + os.close(); } s1 = s.accept (); is = s1.getInputStream (); os = s1.getOutputStream (); is.read (); os.write (reply3.getBytes()); + os.close(); } catch (Exception e) { /* Just need thread to terminate */ + } finally { + try { s.close(); } catch (IOException unused) {} } } }; diff --git a/jdk/test/java/net/URLConnection/ResendPostBody.java b/jdk/test/java/net/URLConnection/ResendPostBody.java index 8bdd5fa09a9..99331584bb5 100644 --- a/jdk/test/java/net/URLConnection/ResendPostBody.java +++ b/jdk/test/java/net/URLConnection/ResendPostBody.java @@ -109,8 +109,11 @@ public class ResendPostBody { while (!finished()) { Thread.sleep (1000); } + out.close(); } catch (Exception e) { System.err.println ("Server Exception: " + e); + } finally { + try { server.close(); } catch (IOException unused) {} } } } @@ -134,7 +137,7 @@ public class ResendPostBody { public void execute () throws Exception { - byte b[] = "X=ABCDEFGHZZZ".getBytes(); + byte b[] = "X=ABCDEFGHZZZ".getBytes(); ss = new ServerSocket (0); server = new Server (ss); @@ -163,8 +166,9 @@ public class ResendPostBody { /* Read the response */ int resp = conURL.getResponseCode (); + server.setFinished (true); + if (resp != 200) throw new RuntimeException ("Response code was not 200: " + resp); - server.setFinished (true); } } diff --git a/jdk/test/java/net/URLConnection/SetIfModifiedSince.java b/jdk/test/java/net/URLConnection/SetIfModifiedSince.java index e5681fc564f..f66d9385c1e 100644 --- a/jdk/test/java/net/URLConnection/SetIfModifiedSince.java +++ b/jdk/test/java/net/URLConnection/SetIfModifiedSince.java @@ -23,7 +23,7 @@ /* @test * @bug 4397096 - * @run main SetIfModifiedSince + * @run main/othervm SetIfModifiedSince * @summary setIfModifiedSince() of HttpURLConnection sets invalid date of default locale */ diff --git a/jdk/test/java/net/URLConnection/TimeoutTest.java b/jdk/test/java/net/URLConnection/TimeoutTest.java index c5c4f58d7a3..e8c32982c8f 100644 --- a/jdk/test/java/net/URLConnection/TimeoutTest.java +++ b/jdk/test/java/net/URLConnection/TimeoutTest.java @@ -43,8 +43,9 @@ public class TimeoutTest { try { Socket s = server.accept (); while (!finished ()) { - Thread.sleep (2000); + Thread.sleep (1000); } + s.close(); } catch (Exception e) { } } @@ -70,9 +71,12 @@ public class TimeoutTest { URL url = new URL ("http://127.0.0.1:"+ss.getLocalPort()); URLConnection urlc = url.openConnection (); InputStream is = urlc.getInputStream (); + throw new RuntimeException("Should have received timeout"); } catch (SocketTimeoutException e) { - s.done (); return; + } finally { + s.done(); + ss.close(); } } } diff --git a/jdk/test/java/net/URLConnection/URLConnectionHeaders.java b/jdk/test/java/net/URLConnection/URLConnectionHeaders.java index 3c162f0e0a2..4896e7a0b58 100644 --- a/jdk/test/java/net/URLConnection/URLConnectionHeaders.java +++ b/jdk/test/java/net/URLConnection/URLConnectionHeaders.java @@ -70,8 +70,10 @@ public class URLConnectionHeaders { w.newLine(); w.flush(); s.close (); - srv.close (); // or else the HTTPURLConnection will retry - } catch (IOException e) { e.printStackTrace();} + } catch (IOException e) { e.printStackTrace(); + } finally { + try { srv.close(); } catch (IOException unused) {} + } } } diff --git a/jdk/test/java/net/URLConnection/ZeroContentLength.java b/jdk/test/java/net/URLConnection/ZeroContentLength.java index 237520ae1b3..3da6ac1aba0 100644 --- a/jdk/test/java/net/URLConnection/ZeroContentLength.java +++ b/jdk/test/java/net/URLConnection/ZeroContentLength.java @@ -58,6 +58,14 @@ public class ZeroContentLength { contentLength = cl; } + static synchronized String getResponse() { + return response; + } + + static synchronized int getContentLength() { + return contentLength; + } + /* * Worker thread to service single connection - can service * multiple http requests on same connection. @@ -71,25 +79,44 @@ public class ZeroContentLength { this.id = id; } + final int CR = '\r'; + final int LF = '\n'; + public void run() { try { s.setSoTimeout(2000); - int max = 100; + int max = 20; // there should only be 20 connections + InputStream in = new BufferedInputStream(s.getInputStream()); for (;;) { - - // read entire request from client - byte b[] = new byte[100]; - InputStream in = s.getInputStream(); - int n, total=0; + // read entire request from client, until CR LF CR LF + int c, total=0; try { - do { - n = in.read(b); - if (n > 0) total += n; - } while (n > 0); - } catch (SocketTimeoutException e) { } + while ((c = in.read()) > 0) { + total++; + if (c == CR) { + if ((c = in.read()) > 0) { + total++; + if (c == LF) { + if ((c = in.read()) > 0) { + total++; + if (c == CR) { + if ((c = in.read()) > 0) { + total++; + if (c == LF) { + break; + } + } + } + } + } + } + } + + } + } catch (SocketTimeoutException e) {} debug("worker " + id + ": Read request from client " + @@ -105,19 +132,20 @@ public class ZeroContentLength { new BufferedOutputStream( s.getOutputStream() )); - out.print("HTTP/1.1 " + response + "\r\n"); - if (contentLength >= 0) { - out.print("Content-Length: " + contentLength + + out.print("HTTP/1.1 " + getResponse() + "\r\n"); + int clen = getContentLength(); + if (clen >= 0) { + out.print("Content-Length: " + clen + "\r\n"); } out.print("\r\n"); - for (int i=0; i upper || got < lower) { throw new RuntimeException ("checkTime failed: got " + got + " expected " + expected); } diff --git a/jdk/test/sun/net/ftp/FtpGetContent.java b/jdk/test/sun/net/ftp/FtpGetContent.java index 46428dd3f14..c736fd43752 100644 --- a/jdk/test/sun/net/ftp/FtpGetContent.java +++ b/jdk/test/sun/net/ftp/FtpGetContent.java @@ -391,6 +391,10 @@ public class FtpGetContent { done = true; } + synchronized boolean done() { + return done; + } + synchronized public void setPortEnabled(boolean ok) { portEnabled = ok; } @@ -431,12 +435,13 @@ public class FtpGetContent { public void run() { try { Socket client; - while (!done) { + while (!done()) { client = server.accept(); (new FtpServerHandler(client)).start(); } - server.close(); } catch(Exception e) { + } finally { + try { server.close(); } catch (IOException unused) {} } } } @@ -463,18 +468,13 @@ public class FtpGetContent { bytesRead = stream.read(buffer); } stream.close(); - server.terminate(); - server.interrupt(); if (totalBytes != filesize) throw new RuntimeException("wrong file size!"); } catch (IOException e) { - try { - server.terminate(); - server.interrupt(); - } catch (Exception e2) { - } throw new RuntimeException(e.getMessage()); + } finally { + server.terminate(); + server.server.close(); } } - } diff --git a/jdk/test/sun/net/ftp/FtpURL.java b/jdk/test/sun/net/ftp/FtpURL.java index c642fb38b32..1d50e49ba20 100644 --- a/jdk/test/sun/net/ftp/FtpURL.java +++ b/jdk/test/sun/net/ftp/FtpURL.java @@ -438,8 +438,9 @@ public class FtpURL { client = server.accept(); (new FtpServerHandler(client)).run(); } - server.close(); } catch(Exception e) { + } finally { + try { server.close(); } catch (IOException unused) {} } } } @@ -448,10 +449,9 @@ public class FtpURL { } public FtpURL() throws Exception { - FtpServer server = null; + FtpServer server = new FtpServer(0); BufferedReader in = null; try { - server = new FtpServer(0); server.start(); int port = server.getPort(); @@ -497,17 +497,14 @@ public class FtpURL { throw new RuntimeException("Incorrect filename received"); if (! "/usr".equals(server.pwd())) throw new RuntimeException("Incorrect pwd received"); - in.close(); // We're done! } catch (Exception e) { - try { - in.close(); - server.terminate(); - server.interrupt(); - } catch(Exception ex) { - } throw new RuntimeException("FTP support error: " + e.getMessage()); + } finally { + try { in.close(); } catch (IOException unused) {} + server.terminate(); + server.server.close(); } } } diff --git a/jdk/test/sun/net/www/http/ChunkedInputStream/ChunkedEncodingWithProgressMonitorTest.java b/jdk/test/sun/net/www/http/ChunkedInputStream/ChunkedEncodingWithProgressMonitorTest.java index 1fc3767cd8e..b2cdf6ec042 100644 --- a/jdk/test/sun/net/www/http/ChunkedInputStream/ChunkedEncodingWithProgressMonitorTest.java +++ b/jdk/test/sun/net/www/http/ChunkedInputStream/ChunkedEncodingWithProgressMonitorTest.java @@ -30,9 +30,7 @@ * @summary ChunkedEncoding unit test; MeteredStream/ProgressData problem */ -import java.io.*; import java.net.*; -import java.security.*; import java.util.BitSet; import sun.net.ProgressMeteringPolicy; import sun.net.ProgressMonitor; @@ -42,8 +40,10 @@ import sun.net.ProgressEvent; public class ChunkedEncodingWithProgressMonitorTest { public static void main (String[] args) throws Exception { ProgressMonitor.setMeteringPolicy(new MyProgressMeteringPolicy()); - ProgressMonitor.getDefault().addProgressListener(new MyProgressListener()); + ProgressListener listener = new MyProgressListener(); + ProgressMonitor.getDefault().addProgressListener(listener); ChunkedEncodingTest.test(); + ProgressMonitor.getDefault().removeProgressListener(listener); if (flag.cardinality() != 3) { throw new RuntimeException("All three methods in ProgressListener"+ diff --git a/jdk/test/sun/net/www/http/ChunkedOutputStream/Test.java b/jdk/test/sun/net/www/http/ChunkedOutputStream/Test.java index 10026cf9412..48d365a7c38 100644 --- a/jdk/test/sun/net/www/http/ChunkedOutputStream/Test.java +++ b/jdk/test/sun/net/www/http/ChunkedOutputStream/Test.java @@ -34,7 +34,7 @@ import com.sun.net.httpserver.*; public class Test implements HttpHandler { - static int count = 0; + static volatile int count = 0; static final String str1 = "Helloworld1234567890abcdefghijklmnopqrstuvwxyz"+ "1234567890abcdefkjsdlkjflkjsldkfjlsdkjflkj"+ @@ -46,9 +46,9 @@ public class Test implements HttpHandler { public void handle(HttpExchange exchange) { String reqbody; try { - switch (count) { - case 0: /* test1 -- keeps conn alive */ - case 1: /* test2 -- closes conn */ + switch (exchange.getRequestURI().toString()) { + case "/test/test1": /* test1 -- keeps conn alive */ + case "/test/test2": /* test2 -- closes conn */ printRequestURI(exchange); reqbody = read(exchange.getRequestBody()); if (!reqbody.equals(str1)) { @@ -72,7 +72,7 @@ public class Test implements HttpHandler { resHeaders.set("Connection", "close"); } break; - case 2: /* test 3 */ + case "/test/test3": /* test 3 */ printRequestURI(exchange); reqbody = read(exchange.getRequestBody()); @@ -93,19 +93,19 @@ public class Test implements HttpHandler { exchange.sendResponseHeaders(200, reqbody.length()); write(exchange.getResponseBody(), reqbody); break; - case 3: /* test 4 */ - case 4: /* test 5 */ + case "/test/test4": /* test 4 */ + case "/test/test5": /* test 5 */ printRequestURI(exchange); break; - case 5: /* test 6 */ + case "/test/test6": /* test 6 */ printRequestURI(exchange); resHeaders = exchange.getResponseHeaders() ; resHeaders.set("Location", "http://foo.bar/"); resHeaders.set("Connection", "close"); exchange.sendResponseHeaders(307, 0); break; - case 6: /* test 7 */ - case 7: /* test 8 */ + case "/test/test7": /* test 7 */ + case "/test/test8": /* test 8 */ printRequestURI(exchange); reqbody = read(exchange.getRequestBody()); if (reqbody != null && !"".equals(reqbody)) { @@ -116,7 +116,7 @@ public class Test implements HttpHandler { resHeaders.set("Connection", "close"); exchange.sendResponseHeaders(200, 0); break; - case 8: /* test 9 */ + case "/test/test9": /* test 9 */ printRequestURI(exchange); reqbody = read(exchange.getRequestBody()); if (!reqbody.equals(str1)) { @@ -134,7 +134,7 @@ public class Test implements HttpHandler { exchange.sendResponseHeaders(200, reqbody.length()); write(exchange.getResponseBody(), reqbody); break; - case 9: /* test10 */ + case "/test/test10": /* test10 */ printRequestURI(exchange); InputStream is = exchange.getRequestBody(); String s = read (is, str1.length()); @@ -158,7 +158,7 @@ public class Test implements HttpHandler { exchange.sendResponseHeaders(200, 0); } break; - case 10: /* test11 */ + case "/test/test11": /* test11 */ printRequestURI(exchange); is = exchange.getRequestBody(); s = read (is, str1.length()); @@ -182,7 +182,7 @@ public class Test implements HttpHandler { exchange.sendResponseHeaders(200, 0); } break; - case 11: /* test12 */ + case "/test/test12": /* test12 */ printRequestURI(exchange); is = exchange.getRequestBody(); @@ -203,8 +203,8 @@ public class Test implements HttpHandler { } break; } - exchange.close(); count ++; + exchange.close(); } catch (IOException e) { e.printStackTrace(); } diff --git a/jdk/test/sun/net/www/http/HttpClient/B6726695.java b/jdk/test/sun/net/www/http/HttpClient/B6726695.java index e601ea70cf7..9e69e8e3d46 100644 --- a/jdk/test/sun/net/www/http/HttpClient/B6726695.java +++ b/jdk/test/sun/net/www/http/HttpClient/B6726695.java @@ -147,6 +147,8 @@ public class B6726695 extends Thread { serverIgnore(s); } catch (IOException e) { e.printStackTrace(); + } finally { + try { server.close(); } catch (IOException unused) {} } } diff --git a/jdk/test/sun/net/www/http/HttpClient/MultiThreadTest.java b/jdk/test/sun/net/www/http/HttpClient/MultiThreadTest.java index 1118365c213..750e4d0d009 100644 --- a/jdk/test/sun/net/www/http/HttpClient/MultiThreadTest.java +++ b/jdk/test/sun/net/www/http/HttpClient/MultiThreadTest.java @@ -100,11 +100,12 @@ public class MultiThreadTest extends Thread { } } catch (Exception e) { throw new RuntimeException (e.getMessage()); - } - synchronized (threadlock) { - threadCounter --; - if (threadCounter == 0) { - threadlock.notifyAll(); + } finally { + synchronized (threadlock) { + threadCounter --; + if (threadCounter == 0) { + threadlock.notifyAll(); + } } } } diff --git a/jdk/test/sun/net/www/http/HttpClient/ProxyTest.java b/jdk/test/sun/net/www/http/HttpClient/ProxyTest.java index e67fd82ac7f..62395f6fc2c 100644 --- a/jdk/test/sun/net/www/http/HttpClient/ProxyTest.java +++ b/jdk/test/sun/net/www/http/HttpClient/ProxyTest.java @@ -47,7 +47,7 @@ public class ProxyTest { private class HttpProxyServer extends Thread { private ServerSocket server; private int port; - private boolean done = false; + private volatile boolean done = false; private String askedUrl; /** @@ -125,12 +125,8 @@ public class ProxyTest { } } - public HttpProxyServer(int port) { - this.port = port; - } - - public HttpProxyServer() { - this(0); + public HttpProxyServer() throws IOException { + server = new ServerSocket(0); } public int getPort() { @@ -148,51 +144,49 @@ public class ProxyTest { */ synchronized public void terminate() { done = true; + try { server.close(); } catch (IOException unused) {} } public void run() { try { - server = new ServerSocket(port); Socket client; while (!done) { client = server.accept(); (new HttpProxyHandler(client)).start(); } - server.close(); } catch (Exception e) { + } finally { + try { server.close(); } catch (IOException unused) {} } } } - public static void main(String[] args) { + public static void main(String[] args) throws Exception { ProxyTest test = new ProxyTest(); } - public ProxyTest() { + public ProxyTest() throws Exception { + BufferedReader in = null; String testURL = "ftp://anonymous:password@myhost.mydomain/index.html"; HttpProxyServer server = new HttpProxyServer(); try { - server.start(); - int port = 0; - while (port == 0) { - Thread.sleep(500); - port = server.getPort(); - } + server.start(); + int port = server.getPort(); - System.setProperty("ftp.proxyHost","localhost"); - System.setProperty("ftp.proxyPort", String.valueOf(port)); - URL url = new URL(testURL); - InputStream ins = url.openStream(); - BufferedReader in = new BufferedReader(new InputStreamReader(ins)); - String line; - do { - line = in.readLine(); - } while (line != null); - in.close(); - server.terminate(); - server.interrupt(); + Proxy ftpProxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("localhost", port)); + URL url = new URL(testURL); + InputStream ins = (url.openConnection(ftpProxy)).getInputStream(); + in = new BufferedReader(new InputStreamReader(ins)); + String line; + do { + line = in.readLine(); + } while (line != null); + in.close(); } catch (Exception e) { e.printStackTrace(); + } finally { + server.terminate(); + try { in.close(); } catch (IOException unused) {} } /* * If the URLs don't match, we've got a bug! diff --git a/jdk/test/sun/net/www/http/KeepAliveCache/KeepAliveTimerThread.java b/jdk/test/sun/net/www/http/KeepAliveCache/KeepAliveTimerThread.java index f0cdf6c77b9..6868de89234 100644 --- a/jdk/test/sun/net/www/http/KeepAliveCache/KeepAliveTimerThread.java +++ b/jdk/test/sun/net/www/http/KeepAliveCache/KeepAliveTimerThread.java @@ -91,9 +91,10 @@ public class KeepAliveTimerThread { out.flush(); s.close(); - server.close(); } catch (Exception e) { e.printStackTrace(); + } finally { + try { server.close(); } catch (IOException unused) {} } } } @@ -118,6 +119,8 @@ public class KeepAliveTimerThread { if (grp.activeCount() > 0) { throw new RuntimeException("Keep-alive thread started in wrong thread group"); } + + grp.destroy(); } } diff --git a/jdk/test/sun/net/www/http/KeepAliveStream/KeepAliveStreamCloseWithWrongContentLength.java b/jdk/test/sun/net/www/http/KeepAliveStream/KeepAliveStreamCloseWithWrongContentLength.java index 866e62e9dd8..18f978c5c41 100644 --- a/jdk/test/sun/net/www/http/KeepAliveStream/KeepAliveStreamCloseWithWrongContentLength.java +++ b/jdk/test/sun/net/www/http/KeepAliveStream/KeepAliveStreamCloseWithWrongContentLength.java @@ -43,10 +43,6 @@ public class KeepAliveStreamCloseWithWrongContentLength { srv = s; } - Socket getSocket () { - return (s); - } - public void run() { try { s = srv.accept (); @@ -57,7 +53,7 @@ public class KeepAliveStreamCloseWithWrongContentLength { is.read(); } OutputStreamWriter ow = - new OutputStreamWriter(s.getOutputStream()); + new OutputStreamWriter((os = s.getOutputStream())); ow.write("HTTP/1.0 200 OK\n"); // Note: The client expects 10 bytes. @@ -71,19 +67,16 @@ public class KeepAliveStreamCloseWithWrongContentLength { // Note: The (buggy) server only sends 9 bytes. ow.write("123456789"); ow.flush(); - ow.close(); } catch (Exception e) { + } finally { + try {if (os != null) { os.close(); }} catch (IOException e) {} } } } - /* - * - */ - - public static void main (String[] args) { + public static void main (String[] args) throws Exception { + ServerSocket serversocket = new ServerSocket (0); try { - ServerSocket serversocket = new ServerSocket (0); int port = serversocket.getLocalPort (); XServer server = new XServer (serversocket); server.start (); @@ -100,11 +93,12 @@ public class KeepAliveStreamCloseWithWrongContentLength { } } is.close(); - server.getSocket().close (); } catch (IOException e) { return; } catch (NullPointerException e) { throw new RuntimeException (e); + } finally { + if (serversocket != null) serversocket.close(); } } } diff --git a/jdk/test/sun/net/www/httptest/HttpServer.java b/jdk/test/sun/net/www/httptest/HttpServer.java index 0a999b8a596..8fcca408f7d 100644 --- a/jdk/test/sun/net/www/httptest/HttpServer.java +++ b/jdk/test/sun/net/www/httptest/HttpServer.java @@ -188,6 +188,7 @@ public class HttpServer { sock.configureBlocking (false); sock.register (selector, SelectionKey.OP_READ); nconn ++; + System.out.println("SERVER: new connection. chan[" + sock + "]"); if (nconn == maxconn) { /* deregister */ listenerKey.cancel (); @@ -197,7 +198,9 @@ public class HttpServer { if (key.isReadable()) { boolean closed; SocketChannel chan = (SocketChannel) key.channel(); + System.out.println("SERVER: connection readable. chan[" + chan + "]"); if (key.attachment() != null) { + System.out.println("Server: comsume"); closed = consume (chan); } else { closed = read (chan, key); @@ -375,6 +378,7 @@ public class HttpServer { synchronized void orderlyCloseChannel (SelectionKey key) throws IOException { SocketChannel ch = (SocketChannel)key.channel (); + System.out.println("SERVER: orderlyCloseChannel chan[" + ch + "]"); ch.socket().shutdownOutput(); key.attach (this); clist.add (key); @@ -382,6 +386,8 @@ public class HttpServer { synchronized void abortiveCloseChannel (SelectionKey key) throws IOException { SocketChannel ch = (SocketChannel)key.channel (); + System.out.println("SERVER: abortiveCloseChannel chan[" + ch + "]"); + Socket s = ch.socket (); s.setSoLinger (true, 0); ch.close(); diff --git a/jdk/test/sun/net/www/protocol/http/DigestTest.java b/jdk/test/sun/net/www/protocol/http/DigestTest.java index ba17d52940d..c9d82fdc264 100644 --- a/jdk/test/sun/net/www/protocol/http/DigestTest.java +++ b/jdk/test/sun/net/www/protocol/http/DigestTest.java @@ -95,10 +95,11 @@ class DigestServer extends Thread { os.write (reply.getBytes()); Thread.sleep (2000); s1.close (); - } - catch (Exception e) { + } catch (Exception e) { System.out.println (e); e.printStackTrace(); + } finally { + try { s.close(); } catch (IOException unused) {} } } @@ -204,15 +205,12 @@ public class DigestTest { public static void main(String[] args) throws Exception { - int nLoops = 1; - int nSize = 10; - int port, n =0; - byte b[] = new byte[nSize]; + int port; DigestServer server; ServerSocket sock; try { - sock = new ServerSocket (5000); + sock = new ServerSocket (0); port = sock.getLocalPort (); } catch (Exception e) { @@ -225,21 +223,18 @@ public class DigestTest { boolean passed = false; try { - Authenticator.setDefault (new MyAuthenticator ()); String s = "http://localhost:" + port + DigestServer.uri; URL url = new URL(s); java.net.URLConnection conURL = url.openConnection(); InputStream in = conURL.getInputStream(); - int c; - while ((c = in.read ()) != -1) { - } + while (in.read () != -1) {} in.close (); - } - catch(ProtocolException e) { + } catch(ProtocolException e) { passed = true; } + if (!passed) { throw new RuntimeException ("Expected a ProtocolException from wrong password"); } From c7d240fc1aa3c5294083547858735c5831a11b6d Mon Sep 17 00:00:00 2001 From: Chris Hegarty Date: Wed, 21 Jul 2010 13:52:38 +0100 Subject: [PATCH 16/56] 6970262: TEST_BUG: test/java/net/NetworkInterface/IPv4Only.java has wrong test name in @run tag Reviewed-by: alanb, dsamersoff --- jdk/test/java/net/NetworkInterface/IPv4Only.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdk/test/java/net/NetworkInterface/IPv4Only.java b/jdk/test/java/net/NetworkInterface/IPv4Only.java index dcbfac1ac2e..4d0bc3d404c 100644 --- a/jdk/test/java/net/NetworkInterface/IPv4Only.java +++ b/jdk/test/java/net/NetworkInterface/IPv4Only.java @@ -23,7 +23,7 @@ /* @test * @bug 6964714 - * @run main/othervm NetworkInterfaceV6List + * @run main/othervm IPv4Only * @summary Test the networkinterface listing with java.net.preferIPv4Stack=true. */ From 11b424e02ba91b2796886adb21c99edfcf5e92ba Mon Sep 17 00:00:00 2001 From: Alan Bateman Date: Wed, 21 Jul 2010 18:08:46 +0100 Subject: [PATCH 17/56] 6963907: (so) Socket adapter need to implement sendUrgentData Reviewed-by: chegar --- jdk/make/java/nio/mapfile-linux | 1 + jdk/make/java/nio/mapfile-solaris | 1 + .../classes/sun/nio/ch/SocketAdaptor.java | 7 +- .../classes/sun/nio/ch/SocketChannelImpl.java | 33 +++ .../native/sun/nio/ch/SocketChannelImpl.c | 8 + .../native/sun/nio/ch/SocketChannelImpl.c | 13 ++ .../nio/channels/SocketChannel/OutOfBand.java | 191 ++++++++++++++++++ 7 files changed, 253 insertions(+), 1 deletion(-) create mode 100644 jdk/test/java/nio/channels/SocketChannel/OutOfBand.java diff --git a/jdk/make/java/nio/mapfile-linux b/jdk/make/java/nio/mapfile-linux index 028e4150d50..13cc1cd01ec 100644 --- a/jdk/make/java/nio/mapfile-linux +++ b/jdk/make/java/nio/mapfile-linux @@ -119,6 +119,7 @@ SUNWprivate_1.1 { Java_sun_nio_ch_ServerSocketChannelImpl_accept0; Java_sun_nio_ch_ServerSocketChannelImpl_initIDs; Java_sun_nio_ch_SocketChannelImpl_checkConnect; + Java_sun_nio_ch_SocketChannelImpl_sendOutOfBandData; Java_sun_nio_ch_UnixAsynchronousServerSocketChannelImpl_accept0; Java_sun_nio_ch_UnixAsynchronousServerSocketChannelImpl_initIDs; Java_sun_nio_ch_UnixAsynchronousSocketChannelImpl_checkConnect; diff --git a/jdk/make/java/nio/mapfile-solaris b/jdk/make/java/nio/mapfile-solaris index 11a74f36713..2b80e4e801e 100644 --- a/jdk/make/java/nio/mapfile-solaris +++ b/jdk/make/java/nio/mapfile-solaris @@ -106,6 +106,7 @@ SUNWprivate_1.1 { Java_sun_nio_ch_ServerSocketChannelImpl_accept0; Java_sun_nio_ch_ServerSocketChannelImpl_initIDs; Java_sun_nio_ch_SocketChannelImpl_checkConnect; + Java_sun_nio_ch_SocketChannelImpl_sendOutOfBandData; Java_sun_nio_ch_UnixAsynchronousServerSocketChannelImpl_accept0; Java_sun_nio_ch_UnixAsynchronousServerSocketChannelImpl_initIDs; Java_sun_nio_ch_UnixAsynchronousSocketChannelImpl_checkConnect; diff --git a/jdk/src/share/classes/sun/nio/ch/SocketAdaptor.java b/jdk/src/share/classes/sun/nio/ch/SocketAdaptor.java index 583835727e8..7ff9a3075f9 100644 --- a/jdk/src/share/classes/sun/nio/ch/SocketAdaptor.java +++ b/jdk/src/share/classes/sun/nio/ch/SocketAdaptor.java @@ -336,7 +336,12 @@ public class SocketAdaptor } public void sendUrgentData(int data) throws IOException { - throw new SocketException("Urgent data not supported"); + synchronized (sc.blockingLock()) { + if (!sc.isBlocking()) + throw new IllegalBlockingModeException(); + int n = sc.sendOutOfBandData((byte)data); + assert n == 1; + } } public void setOOBInline(boolean on) throws SocketException { diff --git a/jdk/src/share/classes/sun/nio/ch/SocketChannelImpl.java b/jdk/src/share/classes/sun/nio/ch/SocketChannelImpl.java index 2539007afd1..ee84a0e626c 100644 --- a/jdk/src/share/classes/sun/nio/ch/SocketChannelImpl.java +++ b/jdk/src/share/classes/sun/nio/ch/SocketChannelImpl.java @@ -498,6 +498,36 @@ class SocketChannelImpl return write0(Util.subsequence(srcs, offset, length)); } + // package-private + int sendOutOfBandData(byte b) throws IOException { + synchronized (writeLock) { + ensureWriteOpen(); + int n = 0; + try { + begin(); + synchronized (stateLock) { + if (!isOpen()) + return 0; + writerThread = NativeThread.current(); + } + for (;;) { + n = sendOutOfBandData(fd, b); + if ((n == IOStatus.INTERRUPTED) && isOpen()) + continue; + return IOStatus.normalize(n); + } + } finally { + writerCleanup(); + end((n > 0) || (n == IOStatus.UNAVAILABLE)); + synchronized (stateLock) { + if ((n <= 0) && (!isOutputOpen)) + throw new AsynchronousCloseException(); + } + assert IOStatus.check(n); + } + } + } + protected void implConfigureBlocking(boolean block) throws IOException { IOUtil.configureBlocking(fd, block); } @@ -957,6 +987,9 @@ class SocketChannelImpl boolean block, boolean ready) throws IOException; + private static native int sendOutOfBandData(FileDescriptor fd, byte data) + throws IOException; + static { Util.load(); nd = new SocketDispatcher(); diff --git a/jdk/src/solaris/native/sun/nio/ch/SocketChannelImpl.c b/jdk/src/solaris/native/sun/nio/ch/SocketChannelImpl.c index faca3732efe..99923f51eec 100644 --- a/jdk/src/solaris/native/sun/nio/ch/SocketChannelImpl.c +++ b/jdk/src/solaris/native/sun/nio/ch/SocketChannelImpl.c @@ -84,3 +84,11 @@ Java_sun_nio_ch_SocketChannelImpl_checkConnect(JNIEnv *env, jobject this, } return 0; } + +JNIEXPORT jint JNICALL +Java_sun_nio_ch_SocketChannelImpl_sendOutOfBandData(JNIEnv* env, jclass this, + jobject fdo, jbyte b) +{ + int n = send(fdval(env, fdo), (const void*)&b, 1, MSG_OOB); + return convertReturnVal(env, n, JNI_FALSE); +} diff --git a/jdk/src/windows/native/sun/nio/ch/SocketChannelImpl.c b/jdk/src/windows/native/sun/nio/ch/SocketChannelImpl.c index 1049dbbb2b0..5ff8b808dde 100644 --- a/jdk/src/windows/native/sun/nio/ch/SocketChannelImpl.c +++ b/jdk/src/windows/native/sun/nio/ch/SocketChannelImpl.c @@ -139,3 +139,16 @@ Java_sun_nio_ch_SocketChannelImpl_checkConnect(JNIEnv *env, jobject this, return 0; } + +JNIEXPORT jint JNICALL +Java_sun_nio_ch_SocketChannelImpl_sendOutOfBandData(JNIEnv* env, jclass this, + jobject fdo, jbyte b) +{ + int n = send(fdval(env, fdo), (const char*)&b, 1, MSG_OOB); + if (n == SOCKET_ERROR) { + handleSocketError(env, WSAGetLastError()); + return IOS_THROWN; + } else { + return n; + } +} diff --git a/jdk/test/java/nio/channels/SocketChannel/OutOfBand.java b/jdk/test/java/nio/channels/SocketChannel/OutOfBand.java new file mode 100644 index 00000000000..83b32667730 --- /dev/null +++ b/jdk/test/java/nio/channels/SocketChannel/OutOfBand.java @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + * @summary Test socket adapter sendUrgentData method + * @bug 6963907 + */ + +import java.net.*; +import java.nio.ByteBuffer; +import java.nio.channels.*; +import java.io.IOException; +import java.util.Random; + +public class OutOfBand { + + private static final Random rand = new Random(); + + public static void main(String[] args) throws Exception { + ServerSocketChannel ssc = null; + SocketChannel sc1 = null; + SocketChannel sc2 = null; + + try { + + // establish loopback connection + ssc = ServerSocketChannel.open().bind(new InetSocketAddress(0)); + InetAddress lh = InetAddress.getLocalHost(); + SocketAddress remote = + new InetSocketAddress(lh, ssc.socket().getLocalPort()); + sc1 = SocketChannel.open(remote); + sc2 = ssc.accept(); + + // enable SO_OOBLINE on server side + sc2.socket().setOOBInline(true); + + // run tests + test1(sc1, sc2); + test2(sc1, sc2); + test3(sc1, sc2); + test4(sc1); + + } finally { + if (sc1 != null) sc1.close(); + if (sc2 != null) sc2.close(); + if (ssc != null) ssc.close(); + } + } + + /** + * Basic test to check that OOB/TCP urgent byte is received. + */ + static void test1(SocketChannel client, SocketChannel server) + throws Exception + { + assert server.socket().getOOBInline(); + ByteBuffer bb = ByteBuffer.allocate(100); + for (int i=0; i<1000; i++) { + int b1 = -127 + rand.nextInt(384); + client.socket().sendUrgentData(b1); + + bb.clear(); + if (server.read(bb) != 1) + throw new RuntimeException("One byte expected"); + bb.flip(); + byte b2 = bb.get(); + if ((byte)b1 != b2) + throw new RuntimeException("Unexpected byte"); + } + } + + /** + * Basic test to check that OOB/TCP urgent byte is received, maybe with + * OOB mark changing. + */ + static void test2(final SocketChannel client, SocketChannel server) + throws Exception + { + assert server.socket().getOOBInline(); + Runnable sender = new Runnable() { + public void run() { + try { + for (int i=0; i<256; i++) + client.socket().sendUrgentData(i); + } catch (IOException ioe) { + ioe.printStackTrace(); + } + } + }; + Thread thr = new Thread(sender); + thr.start(); + + ByteBuffer bb = ByteBuffer.allocate(256); + while (bb.hasRemaining()) { + if (server.read(bb) < 0) + throw new RuntimeException("Unexpected EOF"); + } + bb.flip(); + byte expect = 0; + while (bb.hasRemaining()) { + if (bb.get() != expect) + throw new RuntimeException("Unexpected byte"); + expect++; + } + + thr.join(); + } + + /** + * Test that is close to some real world examples where an urgent byte is + * used to "cancel" a long running query or transaction on the server. + */ + static void test3(SocketChannel client, final SocketChannel server) + throws Exception + { + final int STOP = rand.nextInt(256); + + assert server.socket().getOOBInline(); + Runnable reader = new Runnable() { + public void run() { + ByteBuffer bb = ByteBuffer.allocate(100); + try { + int n = server.read(bb); + if (n != 1) { + String msg = (n < 0) ? "Unexpected EOF" : + "One byte expected"; + throw new RuntimeException(msg); + } + bb.flip(); + if (bb.get() != (byte)STOP) + throw new RuntimeException("Unexpected byte"); + bb.flip(); + server.write(bb); + } catch (IOException ioe) { + ioe.printStackTrace(); + } + + } + }; + + Thread thr = new Thread(reader); + thr.start(); + + // "stop" server + client.socket().sendUrgentData(STOP); + + // wait for server reply + ByteBuffer bb = ByteBuffer.allocate(100); + int n = client.read(bb); + if (n != 1) + throw new RuntimeException("Unexpected number of bytes"); + bb.flip(); + if (bb.get() != (byte)STOP) + throw new RuntimeException("Unexpected reply"); + + thr.join(); + } + + static void test4(SocketChannel sc) throws IOException { + boolean blocking = sc.isBlocking(); + sc.configureBlocking(false); + try { + sc.socket().sendUrgentData(0); + throw new RuntimeException("IllegalBlockingModeException expected"); + } catch (IllegalBlockingModeException x) { + // expected + } finally { + sc.configureBlocking(blocking); + } + } +} From 5d8f395e2b00bba15db2c6de384a865cd0dac02f Mon Sep 17 00:00:00 2001 From: "Daniel D. Daugherty" Date: Wed, 21 Jul 2010 16:58:35 -0700 Subject: [PATCH 18/56] 6941287: 4/4 jrunscriptTest.sh test does not work right under Cygwin Add golden_diff variable for doing proper golden file diffs on Cygwin. Reviewed-by: ohair, dholmes --- jdk/test/sun/tools/jrunscript/common.sh | 12 +++++++++++- jdk/test/sun/tools/jrunscript/jrunscript-eTest.sh | 6 +++--- jdk/test/sun/tools/jrunscript/jrunscript-fTest.sh | 6 +++--- jdk/test/sun/tools/jrunscript/jrunscriptTest.sh | 6 +++--- 4 files changed, 20 insertions(+), 10 deletions(-) diff --git a/jdk/test/sun/tools/jrunscript/common.sh b/jdk/test/sun/tools/jrunscript/common.sh index 3c15672ac3e..2b5bfd652b5 100644 --- a/jdk/test/sun/tools/jrunscript/common.sh +++ b/jdk/test/sun/tools/jrunscript/common.sh @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -43,10 +43,20 @@ setup() { Windows_*) PS=";" FS="\\" + # MKS diff deals with trailing CRs automatically + golden_diff="diff" + ;; + CYGWIN*) + PS=":" + FS="/" + # Cygwin diff needs to be told to ignore trailing CRs + golden_diff="diff --strip-trailing-cr" ;; *) PS=":" FS="/" + # Assume any other platform doesn't have the trailing CR stuff + golden_diff="diff" ;; esac diff --git a/jdk/test/sun/tools/jrunscript/jrunscript-eTest.sh b/jdk/test/sun/tools/jrunscript/jrunscript-eTest.sh index 190f145523b..7291c8708b7 100644 --- a/jdk/test/sun/tools/jrunscript/jrunscript-eTest.sh +++ b/jdk/test/sun/tools/jrunscript/jrunscript-eTest.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -42,7 +42,7 @@ fi rm -f jrunscript-eTest.out 2>/dev/null ${JRUNSCRIPT} -e "println('hello')" > jrunscript-eTest.out 2>&1 -diff jrunscript-eTest.out ${TESTSRC}/dash-e.out +$golden_diff jrunscript-eTest.out ${TESTSRC}/dash-e.out if [ $? != 0 ] then echo "Output of jrunscript -e differ from expected output. Failed." @@ -55,7 +55,7 @@ fi rm -f jrunscript-eTest.out 2>/dev/null ${JRUNSCRIPT} -l js -e "println('hello')" > jrunscript-eTest.out 2>&1 -diff jrunscript-eTest.out ${TESTSRC}/dash-e.out +$golden_diff jrunscript-eTest.out ${TESTSRC}/dash-e.out if [ $? != 0 ] then echo "Output of jrunscript -e differ from expected output. Failed." diff --git a/jdk/test/sun/tools/jrunscript/jrunscript-fTest.sh b/jdk/test/sun/tools/jrunscript/jrunscript-fTest.sh index 9644cd3dbab..fd2feecbd56 100644 --- a/jdk/test/sun/tools/jrunscript/jrunscript-fTest.sh +++ b/jdk/test/sun/tools/jrunscript/jrunscript-fTest.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -42,7 +42,7 @@ fi rm -f jrunscript-fTest.out 2>/dev/null ${JRUNSCRIPT} -f ${TESTSRC}/hello.js > jrunscript-fTest.out 2>&1 -diff jrunscript-fTest.out ${TESTSRC}/dash-f.out +$golden_diff jrunscript-fTest.out ${TESTSRC}/dash-f.out if [ $? != 0 ] then echo "Output of jrunscript -f differ from expected output. Failed." @@ -56,7 +56,7 @@ fi rm -f jrunscript-fTest.out 2>/dev/null ${JRUNSCRIPT} -l js -f ${TESTSRC}/hello.js > jrunscript-fTest.out 2>&1 -diff jrunscript-fTest.out ${TESTSRC}/dash-f.out +$golden_diff jrunscript-fTest.out ${TESTSRC}/dash-f.out if [ $? != 0 ] then echo "Output of jrunscript -f differ from expected output. Failed." diff --git a/jdk/test/sun/tools/jrunscript/jrunscriptTest.sh b/jdk/test/sun/tools/jrunscript/jrunscriptTest.sh index ea411c6b9b4..a07415b1e2d 100644 --- a/jdk/test/sun/tools/jrunscript/jrunscriptTest.sh +++ b/jdk/test/sun/tools/jrunscript/jrunscriptTest.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -49,7 +49,7 @@ java.lang.System.out.println('hello world from script'); new java.lang.Runnable() { run: function() { println('I am runnable'); }}.run(); EOF -diff jrunscriptTest.out ${TESTSRC}/repl.out +$golden_diff jrunscriptTest.out ${TESTSRC}/repl.out if [ $? != 0 ] then echo "Output of jrunscript session differ from expected output. Failed." @@ -67,7 +67,7 @@ java.lang.System.out.println('hello world from script'); new java.lang.Runnable() { run: function() { println('I am runnable'); }}.run(); EOF -diff jrunscriptTest.out ${TESTSRC}/repl.out +$golden_diff jrunscriptTest.out ${TESTSRC}/repl.out if [ $? != 0 ] then echo "Output of jrunscript -l js differ from expected output. Failed." From 9f5d2eb1560d6ea5cacba91a475dfefe4eea68e9 Mon Sep 17 00:00:00 2001 From: "Daniel D. Daugherty" Date: Wed, 21 Jul 2010 16:59:40 -0700 Subject: [PATCH 19/56] 6962804: 4/4 ShellScaffold tests can fail without a specific reason Add more diagnostics for failures. Only copy target file in grepForString when NL is missing. Reviewed-by: ohair, dholmes --- jdk/test/com/sun/jdi/ShellScaffold.sh | 72 +++++++++++++++++++-------- 1 file changed, 52 insertions(+), 20 deletions(-) diff --git a/jdk/test/com/sun/jdi/ShellScaffold.sh b/jdk/test/com/sun/jdi/ShellScaffold.sh index 99193a18ed6..d61acb51094 100644 --- a/jdk/test/com/sun/jdi/ShellScaffold.sh +++ b/jdk/test/com/sun/jdi/ShellScaffold.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright (c) 2002, 2009, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -141,7 +141,10 @@ topPid=$$ cleanup() { if [ -r "$failFile" ] ; then - cat $failFile >& 2 + ls -l "$failFile" >&2 + echo "" >&2 + cat "$failFile" >&2 + echo "" >&2 fi # Kill all processes that have our special @@ -337,6 +340,10 @@ EOF failFile=$tmpFileDir/testFailed debuggeepidFile=$tmpFileDir/debuggeepid rm -f $failFile $debuggeepidFile + if [ -f "$failFile" ]; then + echo "ERROR: unable to delete existing failFile:" >&2 + ls -l "$failFile" >&2 + fi if [ -z "$pkg" ] ; then pkgSlash= @@ -524,6 +531,10 @@ cmd() # See 6562090. Maybe there is a way that the exit # can cause jdb to not get the quit. sleep 5 + + # The exit code value here doesn't matter since this function + # is called as part of a pipeline and it is not the last command + # in the pipeline. exit 1 fi @@ -938,6 +949,10 @@ waitForFinish() done if [ -r "$failFile" ] ; then + ls -l "$failFile" >&2 + echo "" >&2 + cat "$failFile" >&2 + echo "" >&2 exit 1 fi } @@ -946,33 +961,45 @@ waitForFinish() # $3 is the number of lines to search (from the end) grepForString() { - # See bug 6220903. Sometimes the jdb '> ' prompt chars - # get inserted into the string we are searching for - # so ignore those chars. if [ -z "$3" ] ; then theCmd=cat else theCmd="tail -$3" fi + case "$2" in - *\>*) - # Target string contains a > so we better - # not ignore it + *\>*) + # Target string contains a '>' so we better not ignore it $theCmd $1 | $grep -s "$2" > $devnull 2>&1 - return $? + stat="$?" ;; + *) + # Target string does not contain a '>'. + # NOTE: if $1 does not end with a new line, piping it to sed + # doesn't include the chars on the last line. Detect this + # case, and add a new line. + theFile="$1" + if [ `tail -1 "$theFile" | wc -l | sed -e 's@ @@g'` = 0 ] ; then + # The target file doesn't end with a new line so we have + # add one to a copy of the target file so the sed command + # below can filter that last line. + cp "$theFile" "$theFile.tmp" + theFile="$theFile.tmp" + echo >> "$theFile" + fi + + # See bug 6220903. Sometimes the jdb prompt chars ('> ') can + # get interleaved in the target file which can keep us from + # matching the target string. + $theCmd "$theFile" | sed -e 's@> @@g' -e 's@>@@g' \ + | $grep -s "$2" > $devnull 2>&1 + stat=$? + if [ "$theFile" != "$1" ]; then + # remove the copy of the target file + rm -f "$theFile" + fi + unset theFile esac - # Target string does not contain a >. - # Ignore > and '> ' in the file. - # NOTE: if $1 does not end with a new line, piping it to sed doesn't include the - # chars on the last line. Detect this case, and add a new line. - cp $1 $1.tmp - if [ `tail -1 $1.tmp | wc -l | sed -e 's@ @@g'` = 0 ] ; then - echo >> $1.tmp - fi - $theCmd $1.tmp | sed -e 's@> @@g' -e 's@>@@g' | $grep -s "$2" > $devnull 2>&1 - stat=$? - rm -f $1.tmp return $stat } @@ -1037,6 +1064,11 @@ pass() echo echo "--Done: test passed" exit 0 + else + ls -l "$failFile" >&2 + echo "" >&2 + cat "$failFile" >&2 + echo "" >&2 fi } From 7dea7787e2746e9280e030a5b243ccc8c8311548 Mon Sep 17 00:00:00 2001 From: "Daniel D. Daugherty" Date: Wed, 21 Jul 2010 17:01:31 -0700 Subject: [PATCH 20/56] 6964018: 3/4 AnonLoggerWeakRefLeak and LoggerWeakRefLeak can fail in JPRT Refactor test/sun/tools/common/* code and refactor AnonLoggerWeakRefLeak and LoggerWeakRefLeak to use it. Reviewed-by: ohair, alanb --- .../util/logging/AnonLoggerWeakRefLeak.java | 32 +- .../util/logging/AnonLoggerWeakRefLeak.sh | 220 ++++++------ .../java/util/logging/LoggerWeakRefLeak.java | 33 +- .../java/util/logging/LoggerWeakRefLeak.sh | 218 ++++++------ jdk/test/sun/tools/common/ApplicationSetup.sh | 205 ++++++++++-- jdk/test/sun/tools/common/CommonSetup.sh | 102 ++++-- jdk/test/sun/tools/common/CommonTests.sh | 314 ++++++++++++++++++ .../common/ShutdownSimpleApplication.java | 30 +- .../sun/tools/common/SimpleApplication.java | 91 ++++- .../sun/tools/common/SleeperApplication.java | 59 ++++ jdk/test/sun/tools/jhat/ParseTest.sh | 8 +- jdk/test/sun/tools/jinfo/Basic.sh | 38 ++- jdk/test/sun/tools/jmap/Basic.sh | 29 +- jdk/test/sun/tools/jstack/Basic.sh | 20 +- 14 files changed, 1014 insertions(+), 385 deletions(-) create mode 100644 jdk/test/sun/tools/common/CommonTests.sh create mode 100644 jdk/test/sun/tools/common/SleeperApplication.java diff --git a/jdk/test/java/util/logging/AnonLoggerWeakRefLeak.java b/jdk/test/java/util/logging/AnonLoggerWeakRefLeak.java index 6b651013fbc..ed72e7f4110 100644 --- a/jdk/test/java/util/logging/AnonLoggerWeakRefLeak.java +++ b/jdk/test/java/util/logging/AnonLoggerWeakRefLeak.java @@ -23,24 +23,32 @@ import java.util.logging.*; -public class AnonLoggerWeakRefLeak { - public static int DEFAULT_LOOP_TIME = 60; // time is in seconds +public class AnonLoggerWeakRefLeak extends SimpleApplication { + // The test driver script will allow this program to run until we + // reach DEFAULT_LOOP_TIME or a decrease in instance counts is + // observed. For this particular WeakReference leak, the count + // was always observed to be increasing so if we get a decreasing + // count, then the leak is fixed in the bits being tested. + // Two minutes has been enough time to observe a decrease in + // fixed bits on overloaded systems, but the test will likely + // finish more quickly. + public static int DEFAULT_LOOP_TIME = 120; // time is in seconds - public static void main(String[] args) { + // execute the AnonLoggerWeakRefLeak app work + public void doMyAppWork(String[] args) throws Exception { int loop_time = 0; int max_loop_time = DEFAULT_LOOP_TIME; - if (args.length == 0) { + // args[0] is the port-file + if (args.length < 2) { System.out.println("INFO: using default time of " + max_loop_time + " seconds."); } else { try { - max_loop_time = Integer.parseInt(args[0]); + max_loop_time = Integer.parseInt(args[1]); } catch (NumberFormatException nfe) { - System.err.println("Error: '" + args[0] + throw new RuntimeException("Error: '" + args[1] + "': is not a valid seconds value."); - System.err.println("Usage: AnonLoggerWeakRefLeak [seconds]"); - System.exit(1); } } @@ -73,4 +81,12 @@ public class AnonLoggerWeakRefLeak { System.out.println("INFO: final loop count = " + count); } + + public static void main(String[] args) throws Exception { + AnonLoggerWeakRefLeak myApp = new AnonLoggerWeakRefLeak(); + + SimpleApplication.setMyApp(myApp); + + SimpleApplication.main(args); + } } diff --git a/jdk/test/java/util/logging/AnonLoggerWeakRefLeak.sh b/jdk/test/java/util/logging/AnonLoggerWeakRefLeak.sh index ddbb6efcfcf..1402881275b 100644 --- a/jdk/test/java/util/logging/AnonLoggerWeakRefLeak.sh +++ b/jdk/test/java/util/logging/AnonLoggerWeakRefLeak.sh @@ -1,3 +1,5 @@ +#!/bin/sh + # # Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -23,76 +25,24 @@ # @test # @bug 6942989 -# @ignore until 6964018 is fixed # @summary Check for WeakReference leak in anonymous Logger objects # @author Daniel D. Daugherty # -# @run build AnonLoggerWeakRefLeak -# @run shell/timeout=180 AnonLoggerWeakRefLeak.sh +# @library ../../../sun/tools/common +# @build SimpleApplication ShutdownSimpleApplication +# @build AnonLoggerWeakRefLeak +# @run shell/timeout=240 AnonLoggerWeakRefLeak.sh -# The timeout is: 2 minutes for infrastructure and 1 minute for the test +# The timeout is: 2 minutes for infrastructure and 2 minutes for the test # -if [ "${TESTJAVA}" = "" ] -then - echo "TESTJAVA not set. Test cannot execute. Failed." - exit 1 -fi +. ${TESTSRC}/../../../sun/tools/common/CommonSetup.sh +. ${TESTSRC}/../../../sun/tools/common/ApplicationSetup.sh -if [ "${TESTSRC}" = "" ] -then - echo "TESTSRC not set. Test cannot execute. Failed." - exit 1 -fi - -if [ "${TESTCLASSES}" = "" ] -then - echo "TESTCLASSES not set. Test cannot execute. Failed." - exit 1 -fi - -JAVA="${TESTJAVA}"/bin/java -JMAP="${TESTJAVA}"/bin/jmap -JPS="${TESTJAVA}"/bin/jps - -set -eu TEST_NAME="AnonLoggerWeakRefLeak" TARGET_CLASS="java\.lang\.ref\.WeakReference" -is_cygwin=false -is_mks=false -is_windows=false - -case `uname -s` in -CYGWIN*) - is_cygwin=true - is_windows=true - ;; -Windows_*) - is_mks=true - is_windows=true - ;; -*) - ;; -esac - - -# wrapper for grep -# -grep_cmd() { - set +e - if $is_windows; then - # need dos2unix to get rid of CTRL-M chars from java output - dos2unix | grep "$@" - status="$?" - else - grep "$@" - status="$?" - fi - set -e -} - # MAIN begins here # @@ -105,62 +55,39 @@ fi # see if this version of jmap supports the '-histo:live' option jmap_option="-histo:live" set +e -"${JMAP}" "$jmap_option" 0 > "$TEST_NAME.jmap" 2>&1 -grep '^Usage: ' "$TEST_NAME.jmap" > /dev/null 2>&1 +"${JMAP}" 2>&1 | grep ':live' > /dev/null 2>&1 status="$?" set -e -if [ "$status" = 0 ]; then +if [ "$status" != 0 ]; then echo "INFO: switching jmap option from '$jmap_option'\c" jmap_option="-histo" echo " to '$jmap_option'." fi -"${JAVA}" ${TESTVMOPTS} -classpath "${TESTCLASSES}" \ - "$TEST_NAME" $seconds > "$TEST_NAME.log" 2>&1 & -test_pid="$!" -echo "INFO: starting $TEST_NAME as pid = $test_pid" +# Start application and use TEST_NAME.port for coordination +startApplication "$TEST_NAME" "$TEST_NAME.port" $seconds -# wait for test program to get going -count=0 -while [ "$count" -lt 30 ]; do - sleep 2 - grep_cmd '^INFO: call count = 0$' < "$TEST_NAME.log" > /dev/null 2>&1 - if [ "$status" = 0 ]; then - break - fi - count=`expr $count + 1` -done - -if [ "$count" -ge 30 ]; then - echo "ERROR: $TEST_NAME failed to get going." >&2 - echo "INFO: killing $test_pid" - kill "$test_pid" - exit 1 -elif [ "$count" -gt 1 ]; then - echo "INFO: $TEST_NAME took $count loops to start." -fi - -if $is_cygwin; then - # We need the Windows pid for jmap and not the Cygwin pid. - # Note: '\t' works on Cygwin, but doesn't seem to work on Solaris. - jmap_pid=`"${JPS}"| grep_cmd "[ \t]$TEST_NAME$" | sed 's/[ \t].*//'` - if [ -z "$jmap_pid" ]; then - echo "FAIL: jps could not map Cygwin pid to Windows pid." >&2 - echo "INFO: killing $test_pid" - kill "$test_pid" - exit 2 - fi - echo "INFO: pid = $test_pid maps to Windows pid = $jmap_pid" -else - jmap_pid="$test_pid" -fi +finished_early=false decreasing_cnt=0 increasing_cnt=0 loop_cnt=0 prev_instance_cnt=0 +MAX_JMAP_TRY_CNT=10 +jmap_retry_cnt=0 +loop_cnt_on_retry=0 + while true; do + # see if the target process has finished its run and bail if it has + set +e + grep "^INFO: final loop count = " "$appOutput" > /dev/null 2>&1 + status="$?" + set -e + if [ "$status" = 0 ]; then + break + fi + # Output format for 'jmap -histo' in JDK1.5.0: # # <#bytes> <#instances> @@ -170,38 +97,70 @@ while true; do # : <#instances> <#bytes> # set +e - "${JMAP}" "$jmap_option" "$jmap_pid" > "$TEST_NAME.jmap" 2>&1 + "${JMAP}" "$jmap_option" "$appJavaPid" > "$TEST_NAME.jmap" 2>&1 status="$?" set -e if [ "$status" != 0 ]; then echo "INFO: jmap exited with exit code = $status" - if [ "$loop_cnt" = 0 ]; then - echo "INFO: on the first iteration so no samples were taken." - echo "INFO: start of jmap output:" - cat "$TEST_NAME.jmap" - echo "INFO: end of jmap output." + + # There are intermittent jmap failures; see 6498448. + # + # So far the following have been observed in a jmap call + # that was not in a race with target process termination: + # + # (Solaris specific, 2nd sample) + # : Unable to open door: target process not responding or HotSpot VM not loaded + # The -F option can be used when the target process is not responding + # + # (on Solaris so far) + # java.io.IOException + # + # (on Solaris so far, 1st sample) + # : Permission denied + # + sed 's/^/INFO: /' "$TEST_NAME.jmap" + + if [ "$loop_cnt" = "$loop_cnt_on_retry" ]; then + # loop count hasn't changed + jmap_retry_cnt=`expr $jmap_retry_cnt + 1` + else + # loop count has changed so remember it + jmap_retry_cnt=1 + loop_cnt_on_retry="$loop_cnt" + fi + + # This is '-ge' because we have the original attempt plus + # MAX_JMAP_TRY_CNT - 1 retries. + if [ "$jmap_retry_cnt" -ge "$MAX_JMAP_TRY_CNT" ]; then + echo "INFO: jmap failed $MAX_JMAP_TRY_CNT times in a row" \ + "without making any progress." echo "FAIL: jmap is unable to take any samples." >&2 - echo "INFO: killing $test_pid" - kill "$test_pid" + killApplication exit 2 fi - echo "INFO: The likely reason is that $TEST_NAME has finished running." - break + + # short delay and try again + # Note: sleep 1 didn't help with ": Permission denied" + sleep 2 + echo "INFO: retrying jmap (retry=$jmap_retry_cnt, loop=$loop_cnt)." + continue fi - instance_cnt=`grep_cmd "[ ]$TARGET_CLASS$" \ - < "$TEST_NAME.jmap" \ + set +e + instance_cnt=`grep "${PATTERN_WS}${TARGET_CLASS}${PATTERN_EOL}" \ + "$TEST_NAME.jmap" \ | sed ' # strip leading whitespace; does nothing in JDK1.5.0 - s/^[ ][ ]*// + s/^'"${PATTERN_WS}${PATTERN_WS}"'*// # strip <#bytes> in JDK1.5.0; does nothing otherwise - s/^[1-9][0-9]*[ ][ ]*// + s/^[1-9][0-9]*'"${PATTERN_WS}${PATTERN_WS}"'*// # strip : field; does nothing in JDK1.5.0 - s/^[1-9][0-9]*:[ ][ ]*// + s/^[1-9][0-9]*:'"${PATTERN_WS}${PATTERN_WS}"'*// # strip field - s/[ ].*// + s/'"${PATTERN_WS}"'.*// '` + set -e if [ -z "$instance_cnt" ]; then echo "INFO: instance count is unexpectedly empty" if [ "$loop_cnt" = 0 ]; then @@ -211,8 +170,7 @@ while true; do cat "$TEST_NAME.jmap" echo "INFO: end of jmap output." echo "FAIL: cannot find the instance count value." >&2 - echo "INFO: killing $test_pid" - kill "$test_pid" + killApplication exit 2 fi else @@ -221,7 +179,17 @@ while true; do if [ "$instance_cnt" -gt "$prev_instance_cnt" ]; then increasing_cnt=`expr $increasing_cnt + 1` else + # actually decreasing or the same decreasing_cnt=`expr $decreasing_cnt + 1` + + # For this particular WeakReference leak, the count was + # always observed to be increasing so if we get a decreasing + # or the same count, then the leak is fixed in the bits + # being tested. + echo "INFO: finishing early due to non-increasing instance count." + finished_early=true + killApplication + break fi prev_instance_cnt="$instance_cnt" fi @@ -232,8 +200,22 @@ while true; do loop_cnt=`expr $loop_cnt + 1` done +if [ $finished_early = false ]; then + stopApplication "$TEST_NAME.port" + waitForApplication +fi + +echo "INFO: $TEST_NAME has finished running." echo "INFO: increasing_cnt = $increasing_cnt" echo "INFO: decreasing_cnt = $decreasing_cnt" +if [ "$jmap_retry_cnt" -gt 0 ]; then + echo "INFO: jmap_retry_cnt = $jmap_retry_cnt (in $loop_cnt iterations)" +fi + +if [ "$loop_cnt" = 0 ]; then + echo "FAIL: jmap is unable to take any samples." >&2 + exit 2 +fi echo "INFO: The instance count of" `eval echo $TARGET_CLASS` "objects" if [ "$decreasing_cnt" = 0 ]; then @@ -242,6 +224,6 @@ if [ "$decreasing_cnt" = 0 ]; then exit 2 fi -echo "INFO: is both increasing and decreasing." +echo "INFO: is not always increasing." echo "PASS: This indicates that there is not a memory leak." exit 0 diff --git a/jdk/test/java/util/logging/LoggerWeakRefLeak.java b/jdk/test/java/util/logging/LoggerWeakRefLeak.java index c66d3752100..f93c7be6163 100644 --- a/jdk/test/java/util/logging/LoggerWeakRefLeak.java +++ b/jdk/test/java/util/logging/LoggerWeakRefLeak.java @@ -23,27 +23,32 @@ import java.util.logging.*; -public class LoggerWeakRefLeak { - // AnonLoggerWeakRefLeak checks for one weak reference leak. - // LoggerWeakRefLeak checks for two weak reference leaks so - // this test runs twice as long, by default. +public class LoggerWeakRefLeak extends SimpleApplication { + // The test driver script will allow this program to run until we + // reach DEFAULT_LOOP_TIME or a decrease in instance counts is + // observed. For these particular WeakReference leaks, the count + // was always observed to be increasing so if we get a decreasing + // count, then the leaks are fixed in the bits being tested. + // Two minutes has been enough time to observe a decrease in + // fixed bits on overloaded systems, but the test will likely + // finish more quickly. public static int DEFAULT_LOOP_TIME = 120; // time is in seconds - public static void main(String[] args) { + // execute the LoggerWeakRefLeak app work + public void doMyAppWork(String[] args) throws Exception { int loop_time = 0; int max_loop_time = DEFAULT_LOOP_TIME; - if (args.length == 0) { + // args[0] is the port-file + if (args.length < 2) { System.out.println("INFO: using default time of " + max_loop_time + " seconds."); } else { try { - max_loop_time = Integer.parseInt(args[0]); + max_loop_time = Integer.parseInt(args[1]); } catch (NumberFormatException nfe) { - System.err.println("Error: '" + args[0] + throw new RuntimeException("Error: '" + args[1] + "': is not a valid seconds value."); - System.err.println("Usage: LoggerWeakRefLeak [seconds]"); - System.exit(1); } } @@ -86,4 +91,12 @@ public class LoggerWeakRefLeak { System.out.println("INFO: final loop count = " + count); } + + public static void main(String[] args) throws Exception { + AnonLoggerWeakRefLeak myApp = new AnonLoggerWeakRefLeak(); + + SimpleApplication.setMyApp(myApp); + + SimpleApplication.main(args); + } } diff --git a/jdk/test/java/util/logging/LoggerWeakRefLeak.sh b/jdk/test/java/util/logging/LoggerWeakRefLeak.sh index 95c33c39e82..200e49b9369 100644 --- a/jdk/test/java/util/logging/LoggerWeakRefLeak.sh +++ b/jdk/test/java/util/logging/LoggerWeakRefLeak.sh @@ -1,3 +1,5 @@ +#!/bin/sh + # # Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -23,76 +25,24 @@ # @test # @bug 6942989 -# @ignore until 6964018 is fixed # @summary Check for WeakReference leak in Logger objects # @author Daniel D. Daugherty # -# @run build LoggerWeakRefLeak +# @library ../../../sun/tools/common +# @build SimpleApplication ShutdownSimpleApplication +# @build LoggerWeakRefLeak # @run shell/timeout=240 LoggerWeakRefLeak.sh -# The timeout is: 2 minutes for infrastructure and 1 minute for the test +# The timeout is: 2 minutes for infrastructure and 2 minutes for the test # -if [ "${TESTJAVA}" = "" ] -then - echo "TESTJAVA not set. Test cannot execute. Failed." - exit 1 -fi +. ${TESTSRC}/../../../sun/tools/common/CommonSetup.sh +. ${TESTSRC}/../../../sun/tools/common/ApplicationSetup.sh -if [ "${TESTSRC}" = "" ] -then - echo "TESTSRC not set. Test cannot execute. Failed." - exit 1 -fi - -if [ "${TESTCLASSES}" = "" ] -then - echo "TESTCLASSES not set. Test cannot execute. Failed." - exit 1 -fi - -JAVA="${TESTJAVA}"/bin/java -JMAP="${TESTJAVA}"/bin/jmap -JPS="${TESTJAVA}"/bin/jps - -set -eu TEST_NAME="LoggerWeakRefLeak" TARGET_CLASS="java\.lang\.ref\.WeakReference" -is_cygwin=false -is_mks=false -is_windows=false - -case `uname -s` in -CYGWIN*) - is_cygwin=true - is_windows=true - ;; -Windows_*) - is_mks=true - is_windows=true - ;; -*) - ;; -esac - - -# wrapper for grep -# -grep_cmd() { - set +e - if $is_windows; then - # need dos2unix to get rid of CTRL-M chars from java output - dos2unix | grep "$@" - status="$?" - else - grep "$@" - status="$?" - fi - set -e -} - # MAIN begins here # @@ -105,62 +55,39 @@ fi # see if this version of jmap supports the '-histo:live' option jmap_option="-histo:live" set +e -"${JMAP}" "$jmap_option" 0 > "$TEST_NAME.jmap" 2>&1 -grep '^Usage: ' "$TEST_NAME.jmap" > /dev/null 2>&1 +"${JMAP}" 2>&1 | grep ':live' > /dev/null 2>&1 status="$?" set -e -if [ "$status" = 0 ]; then +if [ "$status" != 0 ]; then echo "INFO: switching jmap option from '$jmap_option'\c" jmap_option="-histo" echo " to '$jmap_option'." fi -"${JAVA}" ${TESTVMOPTS} -classpath "${TESTCLASSES}" \ - "$TEST_NAME" $seconds > "$TEST_NAME.log" 2>&1 & -test_pid="$!" -echo "INFO: starting $TEST_NAME as pid = $test_pid" +# Start application and use TEST_NAME.port for coordination +startApplication "$TEST_NAME" "$TEST_NAME.port" $seconds -# wait for test program to get going -count=0 -while [ "$count" -lt 30 ]; do - sleep 2 - grep_cmd '^INFO: call count = 0$' < "$TEST_NAME.log" > /dev/null 2>&1 - if [ "$status" = 0 ]; then - break - fi - count=`expr $count + 1` -done - -if [ "$count" -ge 30 ]; then - echo "ERROR: $TEST_NAME failed to get going." >&2 - echo "INFO: killing $test_pid" - kill "$test_pid" - exit 1 -elif [ "$count" -gt 1 ]; then - echo "INFO: $TEST_NAME took $count loops to start." -fi - -if $is_cygwin; then - # We need the Windows pid for jmap and not the Cygwin pid. - # Note: '\t' works on Cygwin, but doesn't seem to work on Solaris. - jmap_pid=`"${JPS}"| grep_cmd "[ \t]$TEST_NAME$" | sed 's/[ \t].*//'` - if [ -z "$jmap_pid" ]; then - echo "FAIL: jps could not map Cygwin pid to Windows pid." >&2 - echo "INFO: killing $test_pid" - kill "$test_pid" - exit 2 - fi - echo "INFO: pid = $test_pid maps to Windows pid = $jmap_pid" -else - jmap_pid="$test_pid" -fi +finished_early=false decreasing_cnt=0 increasing_cnt=0 loop_cnt=0 prev_instance_cnt=0 +MAX_JMAP_TRY_CNT=10 +jmap_retry_cnt=0 +loop_cnt_on_retry=0 + while true; do + # see if the target process has finished its run and bail if it has + set +e + grep "^INFO: final loop count = " "$appOutput" > /dev/null 2>&1 + status="$?" + set -e + if [ "$status" = 0 ]; then + break + fi + # Output format for 'jmap -histo' in JDK1.5.0: # # <#bytes> <#instances> @@ -170,38 +97,70 @@ while true; do # : <#instances> <#bytes> # set +e - "${JMAP}" "$jmap_option" "$jmap_pid" > "$TEST_NAME.jmap" 2>&1 + "${JMAP}" "$jmap_option" "$appJavaPid" > "$TEST_NAME.jmap" 2>&1 status="$?" set -e if [ "$status" != 0 ]; then echo "INFO: jmap exited with exit code = $status" - if [ "$loop_cnt" = 0 ]; then - echo "INFO: on the first iteration so no samples were taken." - echo "INFO: start of jmap output:" - cat "$TEST_NAME.jmap" - echo "INFO: end of jmap output." + + # There are intermittent jmap failures; see 6498448. + # + # So far the following have been observed in a jmap call + # that was not in a race with target process termination: + # + # (Solaris specific, 2nd sample) + # : Unable to open door: target process not responding or HotSpot VM not loaded + # The -F option can be used when the target process is not responding + # + # (on Solaris so far) + # java.io.IOException + # + # (on Solaris so far, 1st sample) + # : Permission denied + # + sed 's/^/INFO: /' "$TEST_NAME.jmap" + + if [ "$loop_cnt" = "$loop_cnt_on_retry" ]; then + # loop count hasn't changed + jmap_retry_cnt=`expr $jmap_retry_cnt + 1` + else + # loop count has changed so remember it + jmap_retry_cnt=1 + loop_cnt_on_retry="$loop_cnt" + fi + + # This is '-ge' because we have the original attempt plus + # MAX_JMAP_TRY_CNT - 1 retries. + if [ "$jmap_retry_cnt" -ge "$MAX_JMAP_TRY_CNT" ]; then + echo "INFO: jmap failed $MAX_JMAP_TRY_CNT times in a row" \ + "without making any progress." echo "FAIL: jmap is unable to take any samples." >&2 - echo "INFO: killing $test_pid" - kill "$test_pid" + killApplication exit 2 fi - echo "INFO: The likely reason is that $TEST_NAME has finished running." - break + + # short delay and try again + # Note: sleep 1 didn't help with ": Permission denied" + sleep 2 + echo "INFO: retrying jmap (retry=$jmap_retry_cnt, loop=$loop_cnt)." + continue fi - instance_cnt=`grep_cmd "[ ]$TARGET_CLASS$" \ - < "$TEST_NAME.jmap" \ + set +e + instance_cnt=`grep "${PATTERN_WS}${TARGET_CLASS}${PATTERN_EOL}" \ + "$TEST_NAME.jmap" \ | sed ' # strip leading whitespace; does nothing in JDK1.5.0 - s/^[ ][ ]*// + s/^'"${PATTERN_WS}${PATTERN_WS}"'*// # strip <#bytes> in JDK1.5.0; does nothing otherwise - s/^[1-9][0-9]*[ ][ ]*// + s/^[1-9][0-9]*'"${PATTERN_WS}${PATTERN_WS}"'*// # strip : field; does nothing in JDK1.5.0 - s/^[1-9][0-9]*:[ ][ ]*// + s/^[1-9][0-9]*:'"${PATTERN_WS}${PATTERN_WS}"'*// # strip field - s/[ ].*// + s/'"${PATTERN_WS}"'.*// '` + set -e if [ -z "$instance_cnt" ]; then echo "INFO: instance count is unexpectedly empty" if [ "$loop_cnt" = 0 ]; then @@ -211,8 +170,7 @@ while true; do cat "$TEST_NAME.jmap" echo "INFO: end of jmap output." echo "FAIL: cannot find the instance count value." >&2 - echo "INFO: killing $test_pid" - kill "$test_pid" + killApplication exit 2 fi else @@ -221,7 +179,17 @@ while true; do if [ "$instance_cnt" -gt "$prev_instance_cnt" ]; then increasing_cnt=`expr $increasing_cnt + 1` else + # actually decreasing or the same decreasing_cnt=`expr $decreasing_cnt + 1` + + # For these particular WeakReference leaks, the count was + # always observed to be increasing so if we get a decreasing + # or the same count, then the leaks are fixed in the bits + # being tested. + echo "INFO: finishing early due to non-increasing instance count." + finished_early=true + killApplication + break fi prev_instance_cnt="$instance_cnt" fi @@ -232,8 +200,22 @@ while true; do loop_cnt=`expr $loop_cnt + 1` done +if [ $finished_early = false ]; then + stopApplication "$TEST_NAME.port" + waitForApplication +fi + +echo "INFO: $TEST_NAME has finished running." echo "INFO: increasing_cnt = $increasing_cnt" echo "INFO: decreasing_cnt = $decreasing_cnt" +if [ "$jmap_retry_cnt" -gt 0 ]; then + echo "INFO: jmap_retry_cnt = $jmap_retry_cnt (in $loop_cnt iterations)" +fi + +if [ "$loop_cnt" = 0 ]; then + echo "FAIL: jmap is unable to take any samples." >&2 + exit 2 +fi echo "INFO: The instance count of" `eval echo $TARGET_CLASS` "objects" if [ "$decreasing_cnt" = 0 ]; then @@ -242,6 +224,6 @@ if [ "$decreasing_cnt" = 0 ]; then exit 2 fi -echo "INFO: is both increasing and decreasing." +echo "INFO: is not always increasing." echo "PASS: This indicates that there is not a memory leak." exit 0 diff --git a/jdk/test/sun/tools/common/ApplicationSetup.sh b/jdk/test/sun/tools/common/ApplicationSetup.sh index ea2dec2e654..a04989f502e 100644 --- a/jdk/test/sun/tools/common/ApplicationSetup.sh +++ b/jdk/test/sun/tools/common/ApplicationSetup.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. # 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,54 +24,187 @@ # -# Support function to start and stop a given application +# Support functions to start, stop, wait for or kill a given SimpleApplication -# Starts a given application as background process, usage: -# startApplication [args...] +# Starts a given app as background process, usage: +# startApplication port-file [args...] +# +# The following variables are set: +# +# appJavaPid - application's Java pid +# appOtherPid - pid associated with the app other than appJavaPid +# appPidList - all pids associated with the app +# appOutput - file containing stdout and stderr from the app +# +# Waits for at least one line of output from the app to indicate +# that it is up and running. # -# Waits for application to print something to indicate it is running -# (and initialized). Output is directed to ${TESTCLASSES}/Application.out. -# Sets $pid to be the process-id of the application. - startApplication() { - OUTPUTFILE=${TESTCLASSES}/Application.out - ${JAVA} $1 $2 $3 $4 $5 $6 > ${OUTPUTFILE} & - pid="$!" - - # MKS creates an intermediate shell to launch ${JAVA} so - # ${pid} is not the actual pid. We have put in a small sleep - # to give the intermediate shell process time to launch the - # "java" process. - if [ "$OS" = "Windows" ]; then - sleep 2 - if [ "${isCygwin}" = "true" ] ; then - realpid=`ps -p ${pid} | tail -1 | awk '{print $4;}'` - else - realpid=`ps -o pid,ppid,comm|grep ${pid}|grep "java"|cut -c1-6` - fi - pid=${realpid} - fi - - echo "Waiting for Application to initialize..." - attempts=0 + appOutput="${TESTCLASSES}/Application.out" + + ${JAVA} -classpath "${TESTCLASSES}" "$@" > "$appOutput" 2>&1 & + appJavaPid="$!" + appOtherPid= + appPidList="$appJavaPid" + + echo "INFO: waiting for $1 to initialize..." + _cnt=0 while true; do + # if the app doesn't start then the JavaTest/JTREG timeout will + # kick in so this isn't really a endless loop sleep 1 - out=`tail -1 ${OUTPUTFILE}` - if [ ! -z "$out" ]; then + out=`tail -1 "$appOutput"` + if [ -n "$out" ]; then + # we got some output from the app so it's running break fi - attempts=`expr $attempts + 1` - echo "Waiting $attempts second(s) ..." + _cnt=`expr $_cnt + 1` + echo "INFO: waited $_cnt second(s) ..." done + unset _cnt - echo "Application is process $pid" + if $isWindows; then + # Windows requires special handling + appOtherPid="$appJavaPid" + + if $isCygwin; then + appJavaPid=`ps -p "$appOtherPid" \ + | sed -n ' + # See if $appOtherPid is in PID column; there are sometimes + # non-blanks in column 1 (I and S observed so far) + /^.'"${PATTERN_WS}${PATTERN_WS}*${appOtherPid}${PATTERN_WS}"'/{ + # strip PID column + s/^.'"${PATTERN_WS}${PATTERN_WS}*${appOtherPid}${PATTERN_WS}${PATTERN_WS}"'*// + # strip PPID column + s/^[1-9][0-9]*'"${PATTERN_WS}${PATTERN_WS}"'*// + # strip PGID column + s/^[1-9][0-9]*'"${PATTERN_WS}${PATTERN_WS}"'*// + # strip everything after WINPID column + s/'"${PATTERN_WS}"'.*// + p + q + } + '` + echo "INFO: Cygwin pid=$appOtherPid maps to Windows pid=$appJavaPid" + else + # show PID, PPID and COMM columns only + appJavaPid=`ps -o pid,ppid,comm \ + | sed -n ' + # see if appOtherPid is in either PID or PPID columns + /'"${PATTERN_WS}${appOtherPid}${PATTERN_WS}"'/{ + # see if this is a java command + /java'"${PATTERN_EOL}"'/{ + # strip leading white space + s/^'"${PATTERN_WS}${PATTERN_WS}"'*// + # strip everything after the first word + s/'"${PATTERN_WS}"'.*// + # print the pid and we are done + p + q + } + } + '` + echo "INFO: MKS shell pid=$appOtherPid; Java pid=$appJavaPid" + fi + + if [ -z "$appJavaPid" ]; then + echo "ERROR: could not find app's Java pid." >&2 + killApplication + exit 2 + fi + appPidList="$appOtherPid $appJavaPid" + fi + + echo "INFO: $1 is process $appJavaPid" + echo "INFO: $1 output is in $appOutput" } -# Stops an application by invoking the given class and argument, usage: -# stopApplication + +# Stops a simple application by invoking ShutdownSimpleApplication +# class with a specific port-file, usage: +# stopApplication port-file +# +# Note: When this function returns, the SimpleApplication (or a subclass) +# may still be running because the application has not yet reached the +# shutdown check. +# stopApplication() { - $JAVA -classpath "${TESTCLASSES}" $1 $2 + $JAVA -classpath "${TESTCLASSES}" ShutdownSimpleApplication $1 } + +# Wait for a simple application to stop running. +# +waitForApplication() { + if [ $isWindows = false ]; then + # non-Windows is easy; just one process + echo "INFO: waiting for $appJavaPid" + set +e + wait "$appJavaPid" + set -e + + elif $isCygwin; then + # Cygwin pid and not the Windows pid + echo "INFO: waiting for $appOtherPid" + set +e + wait "$appOtherPid" + set -e + + else # implied isMKS + # MKS has intermediate shell and Java process + echo "INFO: waiting for $appJavaPid" + + # appJavaPid can be empty if pid search in startApplication() failed + if [ -n "$appJavaPid" ]; then + # only need to wait for the Java process + set +e + wait "$appJavaPid" + set -e + fi + fi +} + + +# Kills a simple application by sending a SIGTERM to the appropriate +# process(es); on Windows SIGQUIT (-9) is used. +# +killApplication() +{ + if [ $isWindows = false ]; then + # non-Windows is easy; just one process + echo "INFO: killing $appJavaPid" + set +e + kill -TERM "$appJavaPid" # try a polite SIGTERM first + sleep 2 + # send SIGQUIT (-9) just in case SIGTERM didn't do it + # but don't show any complaints + kill -QUIT "$appJavaPid" > /dev/null 2>&1 + wait "$appJavaPid" + set -e + + elif $isCygwin; then + # Cygwin pid and not the Windows pid + echo "INFO: killing $appOtherPid" + set +e + kill -9 "$appOtherPid" + wait "$appOtherPid" + set -e + + else # implied isMKS + # MKS has intermediate shell and Java process + echo "INFO: killing $appPidList" + set +e + kill -9 $appPidList + set -e + + # appJavaPid can be empty if pid search in startApplication() failed + if [ -n "$appJavaPid" ]; then + # only need to wait for the Java process + set +e + wait "$appJavaPid" + set -e + fi + fi +} diff --git a/jdk/test/sun/tools/common/CommonSetup.sh b/jdk/test/sun/tools/common/CommonSetup.sh index ab8f7fdb13d..02fbc60d165 100644 --- a/jdk/test/sun/tools/common/CommonSetup.sh +++ b/jdk/test/sun/tools/common/CommonSetup.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. # 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,56 +24,94 @@ # -# Common setup for tool tests. +# Common setup for tool tests and other tests that use jtools. # Checks that TESTJAVA, TESTSRC, and TESTCLASSES environment variables are set. -# Creates the following for use by the tool tests -# JAVA java launcher -# JSTACK jstack utility -# JMAP jmap utility -# JINFO jinfo utility -# JHAT jhat utility -# PS path separator (";" or ":") -# OS operating system +# +# Creates the following constants for use by the caller: +# JAVA - java launcher +# JHAT - jhat utility +# JINFO - jinfo utility +# JMAP - jmap utility +# JPS - jps utility +# JSTACK - jstack utility +# OS - operating system name +# PATTERN_EOL - grep or sed end-of-line pattern +# PATTERN_WS - grep or sed whitespace pattern +# PS - path separator (";" or ":") +# +# Sets the following variables: +# +# isCygwin - true if environment is Cygwin +# isMKS - true if environment is MKS +# isLinux - true if OS is Linux +# isSolaris - true if OS is Solaris +# isWindows - true if OS is Windows -if [ "${TESTJAVA}" = "" ] -then - echo "TESTJAVA not set. Test cannot execute. Failed." +if [ -z "${TESTJAVA}" ]; then + echo "ERROR: TESTJAVA not set. Test cannot execute. Failed." exit 1 fi - -if [ "${TESTSRC}" = "" ] -then - echo "TESTSRC not set. Test cannot execute. Failed." + +if [ -z "${TESTSRC}" ]; then + echo "ERROR: TESTSRC not set. Test cannot execute. Failed." exit 1 fi - -if [ "${TESTCLASSES}" = "" ] -then - echo "TESTCLASSES not set. Test cannot execute. Failed." + +if [ -z "${TESTCLASSES}" ]; then + echo "ERROR: TESTCLASSES not set. Test cannot execute. Failed." exit 1 fi - + +# only enable these after checking the expected incoming env variables +set -eu + JAVA="${TESTJAVA}/bin/java" -JSTACK="${TESTJAVA}/bin/jstack" -JMAP="${TESTJAVA}/bin/jmap" -JINFO="${TESTJAVA}/bin/jinfo" JHAT="${TESTJAVA}/bin/jhat" +JINFO="${TESTJAVA}/bin/jinfo" +JMAP="${TESTJAVA}/bin/jmap" +JPS="${TESTJAVA}/bin/jps" +JSTACK="${TESTJAVA}/bin/jstack" + +isCygwin=false +isMKS=false +isLinux=false +isSolaris=false +isUnknownOS=false +isWindows=false OS=`uname -s` +# start with some UNIX like defaults +PATTERN_EOL='$' +# blank and tab +PATTERN_WS='[ ]' +PS=":" + case "$OS" in - Windows* ) - PS=";" - OS="Windows" - ;; CYGWIN* ) - PS=";" OS="Windows" + PATTERN_EOL='[ ]*$' + # blank and tab + PATTERN_WS='[ \t]' isCygwin=true + isWindows=true + ;; + Linux ) + OS="Linux" + isLinux=true + ;; + SunOS ) + OS="Solaris" + isSolaris=true + ;; + Windows* ) + OS="Windows" + PATTERN_EOL='[ ]*$' + PS=";" + isWindows=true ;; * ) - PS=":" + isUnknownOS=true ;; esac - diff --git a/jdk/test/sun/tools/common/CommonTests.sh b/jdk/test/sun/tools/common/CommonTests.sh new file mode 100644 index 00000000000..ae0287a0c32 --- /dev/null +++ b/jdk/test/sun/tools/common/CommonTests.sh @@ -0,0 +1,314 @@ +#!/bin/sh + +# +# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. +# 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 6964018 +# @summary Unit test for common tools infrastructure. +# +# @build SimpleApplication SleeperApplication ShutdownSimpleApplication +# @run shell CommonTests.sh + +. ${TESTSRC}/CommonSetup.sh +. ${TESTSRC}/ApplicationSetup.sh + +# hope for the best: +status=0 + + +# Test program path constants from CommonSetup.sh: +# +for name in JAVA JHAT JINFO JMAP JPS JSTACK; do + eval value=$`echo $name` + + echo "INFO: $name=$value" + if [ -x "$value" ]; then + echo "INFO: '$value' is executable." + else + echo "ERROR: '$value' is not executable." >&2 + status=1 + fi +done + + +# Display flag values from CommonSetup.sh: +# +for name in isCygwin isMKS isLinux isSolaris isUnknownOS isWindows; do + eval value=$`echo $name` + echo "INFO: flag $name=$value" +done + + +# Test OS constant from CommonSetup.sh: +# +if [ -z "$OS" ]; then + echo "ERROR: OS constant cannot be empty." >&2 + status=1 +fi + + +# Display the PATTERN_EOL value: +# +echo "INFO: PATTERN_EOL="`echo "$PATTERN_EOL" | od -c` + + +# Test PATTERN_EOL with 'grep' for a regular line. +# +TESTOUT="${TESTCLASSES}/testout.grep_reg_line_eol" +set +e +echo 'regular line' | grep "line${PATTERN_EOL}" > "$TESTOUT" +set -e +if [ -s "$TESTOUT" ]; then + echo "INFO: PATTERN_EOL works for regular line with grep." +else + echo "ERROR: PATTERN_EOL does not work for regular line with grep." >&2 + status=1 +fi + + +if $isWindows; then + # Test PATTERN_EOL with 'grep' for a CR line. + # + TESTOUT="${TESTCLASSES}/testout.grep_cr_line_eol" + set +e + echo 'CR line ' | grep "line${PATTERN_EOL}" > "$TESTOUT" + set -e + if [ -s "$TESTOUT" ]; then + echo "INFO: PATTERN_EOL works for CR line with grep." + else + echo "ERROR: PATTERN_EOL does not work for CR line with grep." >&2 + status=1 + fi +fi + + +# Test PATTERN_EOL with 'sed' for a regular line. +# +TESTOUT="${TESTCLASSES}/testout.sed_reg_line_eol" +echo 'regular line' | sed -n "/line${PATTERN_EOL}/p" > "$TESTOUT" +if [ -s "$TESTOUT" ]; then + echo "INFO: PATTERN_EOL works for regular line with sed." +else + echo "ERROR: PATTERN_EOL does not work for regular line with sed." >&2 + status=1 +fi + + +if $isWindows; then + # Test PATTERN_EOL with 'sed' for a CR line. + # + TESTOUT="${TESTCLASSES}/testout.sed_cr_line_eol" + echo 'CR line ' | sed -n "/line${PATTERN_EOL}/p" > "$TESTOUT" + if [ -s "$TESTOUT" ]; then + echo "INFO: PATTERN_EOL works for CR line with sed." + else + echo "ERROR: PATTERN_EOL does not work for CR line with sed." >&2 + status=1 + fi +fi + + +# Display the PATTERN_WS value: +# +echo "INFO: PATTERN_WS="`echo "$PATTERN_WS" | od -c` + + +# Test PATTERN_WS with 'grep' for a blank. +# +TESTOUT="${TESTCLASSES}/testout.grep_blank" +set +e +echo 'blank: ' | grep "$PATTERN_WS" > "$TESTOUT" +set -e +if [ -s "$TESTOUT" ]; then + echo "INFO: PATTERN_WS works for blanks with grep." +else + echo "ERROR: PATTERN_WS does not work for blanks with grep." >&2 + status=1 +fi + + +# Test PATTERN_WS with 'grep' for a tab. +# +TESTOUT="${TESTCLASSES}/testout.grep_tab" +set +e +echo 'tab: ' | grep "$PATTERN_WS" > "$TESTOUT" +set -e +if [ -s "$TESTOUT" ]; then + echo "INFO: PATTERN_WS works for tabs with grep." +else + echo "ERROR: PATTERN_WS does not work for tabs with grep." >&2 + status=1 +fi + + +# Test PATTERN_WS with 'sed' for a blank. +# +TESTOUT="${TESTCLASSES}/testout.sed_blank" +echo 'blank: ' | sed -n "/$PATTERN_WS/p" > "$TESTOUT" +if [ -s "$TESTOUT" ]; then + echo "INFO: PATTERN_WS works for blanks with sed." +else + echo "ERROR: PATTERN_WS does not work for blanks with sed." >&2 + status=1 +fi + + +# Test PATTERN_WS with 'sed' for a tab. +# +TESTOUT="${TESTCLASSES}/testout.sed_tab" +echo 'tab: ' | sed -n "/$PATTERN_WS/p" > "$TESTOUT" +if [ -s "$TESTOUT" ]; then + echo "INFO: PATTERN_WS works for tabs with sed." +else + echo "ERROR: PATTERN_WS does not work for tabs with sed." >&2 + status=1 +fi + + +# Test startApplication and use PORTFILE for coordination +# The app sleeps for 30 seconds. +# +PORTFILE="${TESTCLASSES}"/shutdown.port +startApplication SleeperApplication "${PORTFILE}" 30 + + +# Test appJavaPid in "ps" cmd output. +# +TESTOUT="${TESTCLASSES}/testout.ps_app" +set +e +if $isCygwin; then + # On Cygwin, appJavaPid is the Windows pid for the Java process + # and appOtherPid is the Cygwin pid for the Java process. + ps -p "$appOtherPid" \ + | grep "${PATTERN_WS}${appJavaPid}${PATTERN_WS}" > "$TESTOUT" +else + # output only pid and comm columns to avoid mismatches + ps -eo pid,comm \ + | grep "^${PATTERN_WS}*${appJavaPid}${PATTERN_WS}" > "$TESTOUT" +fi +set -e +if [ -s "$TESTOUT" ]; then + echo "INFO: begin appJavaPid=$appJavaPid in 'ps' cmd output:" + cat "$TESTOUT" + echo "INFO: end appJavaPid=$appJavaPid in 'ps' cmd output." +else + echo "ERROR: 'ps' cmd should show appJavaPid=$appJavaPid." >&2 + status=1 +fi + +if [ -n "$appOtherPid" ]; then + # Test appOtherPid in "ps" cmd output, if we have one. + # + TESTOUT="${TESTCLASSES}/testout.ps_other" + set +e + if $isCygwin; then + ps -p "$appOtherPid" \ + | grep "${PATTERN_WS}${appOtherPid}${PATTERN_WS}" > "$TESTOUT" + else + # output only pid and comm columns to avoid mismatches + ps -eo pid,comm \ + | grep "^${PATTERN_WS}*${appOtherPid}${PATTERN_WS}" > "$TESTOUT" + fi + set -e + if [ -s "$TESTOUT" ]; then + echo "INFO: begin appOtherPid=$appOtherPid in 'ps' cmd output:" + cat "$TESTOUT" + echo "INFO: end appOtherPid=$appOtherPid in 'ps' cmd output." + else + echo "ERROR: 'ps' cmd should show appOtherPid=$appOtherPid." >&2 + status=1 + fi +fi + + +# Test stopApplication and PORTFILE for coordination +# +stopApplication "${PORTFILE}" + + +# Test application still running after stopApplication. +# +# stopApplication just lets the app know that it can stop, but the +# app might still be doing work. This test just demonstrates that +# fact and doesn't fail if the app is already done. +# +TESTOUT="${TESTCLASSES}/testout.after_stop" +set +e +if $isCygwin; then + # On Cygwin, appJavaPid is the Windows pid for the Java process + # and appOtherPid is the Cygwin pid for the Java process. + ps -p "$appOtherPid" \ + | grep "${PATTERN_WS}${appJavaPid}${PATTERN_WS}" > "$TESTOUT" +else + # output only pid and comm columns to avoid mismatches + ps -eo pid,comm \ + | grep "^${PATTERN_WS}*${appJavaPid}${PATTERN_WS}" > "$TESTOUT" +fi +set -e +if [ -s "$TESTOUT" ]; then + echo "INFO: it is okay for appJavaPid=$appJavaPid to still be running" \ + "after stopApplication() is called." + echo "INFO: begin 'after_stop' output:" + cat "$TESTOUT" + echo "INFO: end 'after_stop' output." +fi + + +# Test waitForApplication +# +# The app might already be gone so this function shouldn't generate +# a fatal error in either call. +# +waitForApplication + +if [ $isWindows = false ]; then + # Windows can recycle pids quickly so we can't use this test there + TESTOUT="${TESTCLASSES}/testout.after_kill" + set +e + # output only pid and comm columns to avoid mismatches + ps -eo pid,comm \ + | grep "^${PATTERN_WS}*${appJavaPid}${PATTERN_WS}" > "$TESTOUT" + set -e + if [ -s "$TESTOUT" ]; then + echo "ERROR: 'ps' cmd should not show appJavaPid." >&2 + echo "ERROR: begin 'after_kill' output:" >&2 + cat "$TESTOUT" >&2 + echo "ERROR: end 'after_kill' output." >&2 + status=1 + else + echo "INFO: 'ps' cmd does not show appJavaPid after" \ + "waitForApplication() is called." + fi +fi + + +# Test killApplication +# +# The app is already be gone so this function shouldn't generate +# a fatal error. +# +killApplication + +exit $status diff --git a/jdk/test/sun/tools/common/ShutdownSimpleApplication.java b/jdk/test/sun/tools/common/ShutdownSimpleApplication.java index 78ef1d31c2d..314bb579bad 100644 --- a/jdk/test/sun/tools/common/ShutdownSimpleApplication.java +++ b/jdk/test/sun/tools/common/ShutdownSimpleApplication.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,10 +22,13 @@ */ /* + * Used to shutdown SimpleApplication (or a subclass). The argument to + * this class is the name of a file that contains the TCP port number + * on which SimpleApplication (or a subclass) is listening. * - * - * Used to shutdown SimpleApplication. The argument to this class is - * the TCP port number where SimpleApplication is listening. + * Note: When this program returns, the SimpleApplication (or a subclass) + * may still be running because the application has not yet reached the + * shutdown check. */ import java.net.Socket; import java.net.InetSocketAddress; @@ -35,6 +38,11 @@ import java.io.FileInputStream; public class ShutdownSimpleApplication { public static void main(String args[]) throws Exception { + if (args.length != 1) { + throw new RuntimeException("Usage: ShutdownSimpleApplication" + + " port-file"); + } + // read the (TCP) port number from the given file File f = new File(args[0]); @@ -42,21 +50,27 @@ public class ShutdownSimpleApplication { byte b[] = new byte[8]; int n = fis.read(b); if (n < 1) { - throw new RuntimeException("Empty file"); + throw new RuntimeException("Empty port-file"); } fis.close(); String str = new String(b, 0, n, "UTF-8"); - System.out.println("Port number of application is: " + str); + System.out.println("INFO: Port number of SimpleApplication: " + str); int port = Integer.parseInt(str); // Now connect to the port (which will shutdown application) - System.out.println("Connecting to port " + port + - " to shutdown Application ..."); + System.out.println("INFO: Connecting to port " + port + + " to shutdown SimpleApplication ..."); + System.out.flush(); Socket s = new Socket(); s.connect( new InetSocketAddress(port) ); s.close(); + + System.out.println("INFO: done connecting to SimpleApplication."); + System.out.flush(); + + System.exit(0); } } diff --git a/jdk/test/sun/tools/common/SimpleApplication.java b/jdk/test/sun/tools/common/SimpleApplication.java index 050f010a774..c7e6b0bdac4 100644 --- a/jdk/test/sun/tools/common/SimpleApplication.java +++ b/jdk/test/sun/tools/common/SimpleApplication.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,10 +22,12 @@ */ /* + * A simple application used by unit tests. The first argument to this + * class is the name of a file to which a TCP port number can be written. * - * - * A simple application used for tool unit tests. It does nothing else - * bind to a TCP port and wait for a shutdown message. + * By default, this class does nothing other than bind to a TCP port, + * write the TCP port number to a file, and wait for an incoming connection + * in order to complete the application shutdown protocol. */ import java.net.Socket; import java.net.ServerSocket; @@ -33,25 +35,86 @@ import java.io.File; import java.io.FileOutputStream; public class SimpleApplication { - public static void main(String args[]) throws Exception { + private static SimpleApplication myApp; // simple app or a subclass + private static String myAppName; // simple app name + private static int myPort; // coordination port # + private static ServerSocket mySS; // coordination socket + + // protected so a subclass can extend it; not public so creation is + // limited. + protected SimpleApplication() { + // save simple app (or subclass) name for messages + myAppName = getClass().getName(); + } + + // return the simple application (or a subclass) + final public static SimpleApplication getMyApp() { + return myApp; + } + + // set the simple application (for use by a subclass) + final public static void setMyApp(SimpleApplication _myApp) { + myApp = _myApp; + } + + // execute the application finish protocol + final public void doMyAppFinish(String[] args) throws Exception { + System.out.println("INFO: " + myAppName + " is waiting on port: " + + myPort); + System.out.flush(); + + // wait for test harness to connect + Socket s = mySS.accept(); + s.close(); + mySS.close(); + + System.out.println("INFO: " + myAppName + " is shutting down."); + System.out.flush(); + } + + // execute the application start protocol + final public void doMyAppStart(String[] args) throws Exception { + if (args.length < 1) { + throw new RuntimeException("Usage: " + myAppName + + " port-file [arg(s)]"); + } + // bind to a random port - ServerSocket ss = new ServerSocket(0); - int port = ss.getLocalPort(); + mySS = new ServerSocket(0); + myPort = mySS.getLocalPort(); // Write the port number to the given file File f = new File(args[0]); FileOutputStream fos = new FileOutputStream(f); - fos.write( Integer.toString(port).getBytes("UTF-8") ); + fos.write( Integer.toString(myPort).getBytes("UTF-8") ); fos.close(); - System.out.println("Application waiting on port: " + port); + System.out.println("INFO: " + myAppName + " created socket on port: " + + myPort); + System.out.flush(); + } + + // execute the app work (subclass can override this) + public void doMyAppWork(String[] args) throws Exception { + } + + public static void main(String[] args) throws Exception { + if (myApp == null) { + // create myApp since a subclass hasn't done so + myApp = new SimpleApplication(); + } + + myApp.doMyAppStart(args); // do the app start protocol + + System.out.println("INFO: " + myAppName + " is calling doMyAppWork()"); + System.out.flush(); + myApp.doMyAppWork(args); // do the app work + System.out.println("INFO: " + myAppName + " returned from" + + " doMyAppWork()"); System.out.flush(); - // wait for test harness to connect - Socket s = ss.accept(); - s.close(); - ss.close(); + myApp.doMyAppFinish(args); // do the app finish protocol - System.out.println("Application shutdown."); + System.exit(0); } } diff --git a/jdk/test/sun/tools/common/SleeperApplication.java b/jdk/test/sun/tools/common/SleeperApplication.java new file mode 100644 index 00000000000..b96d9b07ac3 --- /dev/null +++ b/jdk/test/sun/tools/common/SleeperApplication.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * 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. + */ + +/* + * An example subclass of SimpleApplication that illustrates how to + * override the doMyAppWork() method. + */ + +public class SleeperApplication extends SimpleApplication { + public static int DEFAULT_SLEEP_TIME = 60; // time is in seconds + + // execute the sleeper app work + public void doMyAppWork(String[] args) throws Exception { + int sleep_time = DEFAULT_SLEEP_TIME; + + // args[0] is the port-file + if (args.length < 2) { + System.out.println("INFO: using default sleep time of " + + sleep_time + " seconds."); + } else { + try { + sleep_time = Integer.parseInt(args[1]); + } catch (NumberFormatException nfe) { + throw new RuntimeException("Error: '" + args[1] + + "': is not a valid seconds value."); + } + } + + Thread.sleep(sleep_time * 1000); // our "work" is to sleep + } + + public static void main(String[] args) throws Exception { + SleeperApplication myApp = new SleeperApplication(); + + SimpleApplication.setMyApp(myApp); + + SimpleApplication.main(args); + } +} diff --git a/jdk/test/sun/tools/jhat/ParseTest.sh b/jdk/test/sun/tools/jhat/ParseTest.sh index 35dc84e1f43..9bc9294eb71 100644 --- a/jdk/test/sun/tools/jhat/ParseTest.sh +++ b/jdk/test/sun/tools/jhat/ParseTest.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -32,7 +32,11 @@ # @run shell ParseTest.sh . ${TESTSRC}/../common/CommonSetup.sh -. ${TESTSRC}/../common/ApplicationSetup.sh + +# all return statuses are checked in this test +set +e + +failed=0 DUMPFILE="minimal.bin" diff --git a/jdk/test/sun/tools/jinfo/Basic.sh b/jdk/test/sun/tools/jinfo/Basic.sh index e88db448e14..57f40af414a 100644 --- a/jdk/test/sun/tools/jinfo/Basic.sh +++ b/jdk/test/sun/tools/jinfo/Basic.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -35,53 +35,57 @@ . ${TESTSRC}/../common/CommonSetup.sh . ${TESTSRC}/../common/ApplicationSetup.sh -# Start application (send output to shutdown.port) +# Start application and use PORTFILE for coordination PORTFILE="${TESTCLASSES}"/shutdown.port -startApplication \ - -classpath "${TESTCLASSES}" SimpleApplication "${PORTFILE}" +startApplication SimpleApplication "${PORTFILE}" + +# all return statuses are checked in this test +set +e failed=0 -if [ "$OS" != "Windows" ]; then +if [ $isWindows = false ]; then # -sysprops option - ${JINFO} -sysprops $pid + ${JINFO} -sysprops $appJavaPid if [ $? != 0 ]; then failed=1; fi # -flags option - ${JINFO} -flags $pid + ${JINFO} -flags $appJavaPid if [ $? != 0 ]; then failed=1; fi # no option - ${JINFO} $pid + ${JINFO} $appJavaPid if [ $? != 0 ]; then failed=1; fi fi # -flag option -${JINFO} -flag +PrintGC $pid +${JINFO} -flag +PrintGC $appJavaPid if [ $? != 0 ]; then failed=1; fi -${JINFO} -flag -PrintGC $pid +${JINFO} -flag -PrintGC $appJavaPid if [ $? != 0 ]; then failed=1; fi -${JINFO} -flag PrintGC $pid +${JINFO} -flag PrintGC $appJavaPid if [ $? != 0 ]; then failed=1; fi -if [ "$OS" = "SunOS" ]; then +if $isSolaris; then - ${JINFO} -flag +ExtendedDTraceProbes $pid + ${JINFO} -flag +ExtendedDTraceProbes $appJavaPid if [ $? != 0 ]; then failed=1; fi - ${JINFO} -flag -ExtendedDTraceProbes $pid + ${JINFO} -flag -ExtendedDTraceProbes $appJavaPid if [ $? != 0 ]; then failed=1; fi - ${JINFO} -flag ExtendedDTraceProbes $pid + ${JINFO} -flag ExtendedDTraceProbes $appJavaPid if [ $? != 0 ]; then failed=1; fi fi -stopApplication ShutdownSimpleApplication "${PORTFILE}" +set -e + +stopApplication "${PORTFILE}" +waitForApplication exit $failed - diff --git a/jdk/test/sun/tools/jmap/Basic.sh b/jdk/test/sun/tools/jmap/Basic.sh index 3b4e872e71f..f1c0b34b443 100644 --- a/jdk/test/sun/tools/jmap/Basic.sh +++ b/jdk/test/sun/tools/jmap/Basic.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -35,24 +35,25 @@ . ${TESTSRC}/../common/CommonSetup.sh . ${TESTSRC}/../common/ApplicationSetup.sh -# Start application (send output to shutdown.port) +# Start application and use PORTFILE for coordination PORTFILE="${TESTCLASSES}"/shutdown.port -startApplication \ - -classpath "${TESTCLASSES}" SimpleApplication "${PORTFILE}" +startApplication SimpleApplication "${PORTFILE}" + +# all return statuses are checked in this test +set +e failed=0 # -histo[:live] option -${JMAP} -histo $pid +${JMAP} -histo $appJavaPid if [ $? != 0 ]; then failed=1; fi -${JMAP} -histo:live $pid +${JMAP} -histo:live $appJavaPid if [ $? != 0 ]; then failed=1; fi # -dump option -p=`expr $pid` -DUMPFILE="java_pid${p}.hprof" -${JMAP} -dump:format=b,file=${DUMPFILE} $pid +DUMPFILE="java_pid${appJavaPid}.hprof" +${JMAP} -dump:format=b,file=${DUMPFILE} $appJavaPid if [ $? != 0 ]; then failed=1; fi # check that heap dump is parsable @@ -63,7 +64,7 @@ if [ $? != 0 ]; then failed=1; fi rm ${DUMPFILE} # -dump:live option -${JMAP} -dump:live,format=b,file=${DUMPFILE} $pid +${JMAP} -dump:live,format=b,file=${DUMPFILE} $appJavaPid if [ $? != 0 ]; then failed=1; fi # check that heap dump is parsable @@ -71,9 +72,11 @@ ${JHAT} -parseonly true ${DUMPFILE} if [ $? != 0 ]; then failed=1; fi # dump file is large so remove it -rm ${DUMPFILE} +rm -f ${DUMPFILE} -stopApplication ShutdownSimpleApplication "${PORTFILE}" +set -e + +stopApplication "${PORTFILE}" +waitForApplication exit $failed - diff --git a/jdk/test/sun/tools/jstack/Basic.sh b/jdk/test/sun/tools/jstack/Basic.sh index dcbdd4bc753..1a2b8eb37a9 100644 --- a/jdk/test/sun/tools/jstack/Basic.sh +++ b/jdk/test/sun/tools/jstack/Basic.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -35,22 +35,26 @@ . ${TESTSRC}/../common/CommonSetup.sh . ${TESTSRC}/../common/ApplicationSetup.sh -# Start application (send output to shutdown.port) +# Start application and use PORTFILE for coordination PORTFILE="${TESTCLASSES}"/shutdown.port -startApplication \ - -classpath "${TESTCLASSES}" SimpleApplication "${PORTFILE}" +startApplication SimpleApplication "${PORTFILE}" + +# all return statuses are checked in this test +set +e failed=0 # normal -$JSTACK $pid 2>&1 +$JSTACK $appJavaPid 2>&1 if [ $? != 0 ]; then failed=1; fi # long -$JSTACK -l $pid 2>&1 +$JSTACK -l $appJavaPid 2>&1 if [ $? != 0 ]; then failed=1; fi -stopApplication ShutdownSimpleApplication "${PORTFILE}" +set -e + +stopApplication "${PORTFILE}" +waitForApplication exit $failed - From 762e078636c6cc8908dd1d98e1f4e37c80908581 Mon Sep 17 00:00:00 2001 From: Tom Rodriguez Date: Thu, 22 Jul 2010 15:29:22 -0700 Subject: [PATCH 21/56] 6970566: runThese fails with SIGSEGV Reviewed-by: kvn --- hotspot/src/share/vm/code/codeBlob.cpp | 6 +++++- hotspot/src/share/vm/code/codeBlob.hpp | 3 +-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/hotspot/src/share/vm/code/codeBlob.cpp b/hotspot/src/share/vm/code/codeBlob.cpp index 33b267be711..b4c21c91f82 100644 --- a/hotspot/src/share/vm/code/codeBlob.cpp +++ b/hotspot/src/share/vm/code/codeBlob.cpp @@ -202,6 +202,11 @@ void BufferBlob::free( BufferBlob *blob ) { //---------------------------------------------------------------------------------------------------- // Implementation of AdapterBlob +AdapterBlob::AdapterBlob(int size, CodeBuffer* cb) : + BufferBlob("I2C/C2I adapters", size, cb) { + CodeCache::commit(this); +} + AdapterBlob* AdapterBlob::create(CodeBuffer* cb) { ThreadInVMfromUnknown __tiv; // get to VM state in case we block on CodeCache_lock @@ -210,7 +215,6 @@ AdapterBlob* AdapterBlob::create(CodeBuffer* cb) { { MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); blob = new (size) AdapterBlob(size, cb); - CodeCache::commit(blob); } // Track memory usage statistic after releasing CodeCache_lock MemoryService::track_code_cache_memory_usage(); diff --git a/hotspot/src/share/vm/code/codeBlob.hpp b/hotspot/src/share/vm/code/codeBlob.hpp index 1fc0c2f0c1e..790f15be64b 100644 --- a/hotspot/src/share/vm/code/codeBlob.hpp +++ b/hotspot/src/share/vm/code/codeBlob.hpp @@ -219,8 +219,7 @@ class BufferBlob: public CodeBlob { class AdapterBlob: public BufferBlob { private: - AdapterBlob(int size) : BufferBlob("I2C/C2I adapters", size) {} - AdapterBlob(int size, CodeBuffer* cb) : BufferBlob("I2C/C2I adapters", size, cb) {} + AdapterBlob(int size, CodeBuffer* cb); public: // Creation From 70d788010247000ee6dd0594310acdc657f602c9 Mon Sep 17 00:00:00 2001 From: Alexey Utkin Date: Fri, 23 Jul 2010 18:59:48 +0400 Subject: [PATCH 22/56] 6969851: VM hangs/crashes in FileDialog test (VS2008/2010 build) Reviewed-by: prr, art --- jdk/src/windows/native/sun/windows/awt.h | 30 +++++++++++++++++------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/jdk/src/windows/native/sun/windows/awt.h b/jdk/src/windows/native/sun/windows/awt.h index 0d1c7d9064a..8fdef922369 100644 --- a/jdk/src/windows/native/sun/windows/awt.h +++ b/jdk/src/windows/native/sun/windows/awt.h @@ -310,24 +310,32 @@ typedef JLocalRef JLClass; * Class to encapsulate the extraction of the java string contents * into a buffer and the cleanup of the buffer */ - class JavaStringBuffer +class JavaStringBuffer { protected: LPWSTR m_pStr; jsize m_dwSize; + LPWSTR getNonEmptyString() { + return (NULL==m_pStr) + ? L"" + : m_pStr; + } public: JavaStringBuffer(jsize cbTCharCount) { m_dwSize = cbTCharCount; - m_pStr = (LPWSTR)safe_Malloc( (m_dwSize+1)*sizeof(WCHAR) ); + m_pStr = (0 == m_dwSize) + ? NULL + : (LPWSTR)safe_Malloc( (m_dwSize+1)*sizeof(WCHAR) ); } JavaStringBuffer(JNIEnv *env, jstring text) { - if (NULL == text) { - m_pStr = L""; - m_dwSize = 0; + m_dwSize = (NULL == text) + ? 0 + : env->GetStringLength(text); + if (0 == m_dwSize) { + m_pStr = NULL; } else { - m_dwSize = env->GetStringLength(text); m_pStr = (LPWSTR)safe_Malloc( (m_dwSize+1)*sizeof(WCHAR) ); env->GetStringRegion(text, 0, m_dwSize, reinterpret_cast(m_pStr)); m_pStr[m_dwSize] = 0; @@ -341,12 +349,16 @@ public: void Resize(jsize cbTCharCount) { m_dwSize = cbTCharCount; + //It is ok to have non-null terminated string here. + //The function is used only for space reservation in staff buffer for + //followed data copying process. And that is the reason why we ignore + //the special case m_dwSize==0 here. m_pStr = (LPWSTR)safe_Realloc(m_pStr, (m_dwSize+1)*sizeof(WCHAR) ); } //we are in UNICODE now, so LPWSTR:=:LPTSTR - operator LPWSTR() { return m_pStr; } - operator LPARAM() { return (LPARAM)m_pStr; } - void *GetData() { return (void *)m_pStr; } + operator LPWSTR() { return getNonEmptyString(); } + operator LPARAM() { return (LPARAM)getNonEmptyString(); } + void *GetData() { return (void *)getNonEmptyString(); } jsize GetSize() { return m_dwSize; } }; From 575bf80be621a7ad15b254cc24697a1a565a744c Mon Sep 17 00:00:00 2001 From: Vinnie Ryan Date: Fri, 23 Jul 2010 17:41:47 +0100 Subject: [PATCH 23/56] 6676075: RegistryContext (com.sun.jndi.url.rmi.rmiURLContext) coding problem Reviewed-by: mullan --- .../jndi/rmi/registry/RegistryContext.java | 2 +- .../ContextWithNullProperties.java | 50 +++++++++++++++++++ 2 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 jdk/test/com/sun/jndi/rmi/registry/RegistryContext/ContextWithNullProperties.java diff --git a/jdk/src/share/classes/com/sun/jndi/rmi/registry/RegistryContext.java b/jdk/src/share/classes/com/sun/jndi/rmi/registry/RegistryContext.java index 07173c1028c..4e34eec6229 100644 --- a/jdk/src/share/classes/com/sun/jndi/rmi/registry/RegistryContext.java +++ b/jdk/src/share/classes/com/sun/jndi/rmi/registry/RegistryContext.java @@ -81,7 +81,7 @@ public class RegistryContext implements Context, Referenceable { } RMIClientSocketFactory socketFactory = - (RMIClientSocketFactory) env.get(SOCKET_FACTORY); + (RMIClientSocketFactory) environment.get(SOCKET_FACTORY); registry = getRegistry(host, port, socketFactory); this.host = host; this.port = port; diff --git a/jdk/test/com/sun/jndi/rmi/registry/RegistryContext/ContextWithNullProperties.java b/jdk/test/com/sun/jndi/rmi/registry/RegistryContext/ContextWithNullProperties.java new file mode 100644 index 00000000000..f8706df0caf --- /dev/null +++ b/jdk/test/com/sun/jndi/rmi/registry/RegistryContext/ContextWithNullProperties.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * 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 6676075 + * @summary RegistryContext (com.sun.jndi.url.rmi.rmiURLContext) coding problem + */ + +import java.rmi.RemoteException; +import java.rmi.registry.LocateRegistry; + +import com.sun.jndi.rmi.registry.*; + +public class ContextWithNullProperties { + + public static void main(String[] args) throws Exception { + + // Create registry on port 1099 if one is not already running. + try { + LocateRegistry.createRegistry(1099); + } catch (RemoteException e) { + } + + System.out.println("Connecting to the default Registry..."); + // Connect to the default Registry. + // Pass null as the JNDI environment properties (see final argument) + RegistryContext ctx = new RegistryContext(null, -1, null); + } +} From f5561769de62777151cb673ec8b14edef0d6324c Mon Sep 17 00:00:00 2001 From: Xue-Lei Andrew Fan Date: Sat, 24 Jul 2010 22:59:41 +0800 Subject: [PATCH 24/56] 6867345: Turkish regional options cause NPE in sun.security.x509.AlgorithmId.algOID Reviewed-by: mullan, weijun --- .../sun/security/krb5/Credentials.java | 3 +- .../sun/security/pkcs/PKCS9Attribute.java | 5 ++- .../sun/security/pkcs11/P11Cipher.java | 5 ++- .../sun/security/pkcs11/P11RSACipher.java | 4 +- .../provider/certpath/URICertStore.java | 5 ++- .../classes/sun/security/util/Debug.java | 5 ++- .../share/classes/sun/security/x509/AVA.java | 4 +- .../sun/security/x509/AlgorithmId.java | 22 ++++++---- .../classes/sun/security/x509/DNSName.java | 8 ++-- .../classes/sun/security/x509/RFC822Name.java | 8 ++-- .../x509/AlgorithmId/TurkishRegion.java | 40 +++++++++++++++++++ 11 files changed, 84 insertions(+), 25 deletions(-) create mode 100644 jdk/test/sun/security/x509/AlgorithmId/TurkishRegion.java diff --git a/jdk/src/share/classes/sun/security/krb5/Credentials.java b/jdk/src/share/classes/sun/security/krb5/Credentials.java index b7ae4aaee65..6896aa18e95 100644 --- a/jdk/src/share/classes/sun/security/krb5/Credentials.java +++ b/jdk/src/share/classes/sun/security/krb5/Credentials.java @@ -36,6 +36,7 @@ import sun.security.krb5.internal.ccache.CredentialsCache; import sun.security.krb5.internal.crypto.EType; import java.io.IOException; import java.util.Date; +import java.util.Locale; import java.net.InetAddress; /** @@ -287,7 +288,7 @@ public class Credentials { // The default ticket cache on Windows is not a file. String os = java.security.AccessController.doPrivileged( new sun.security.action.GetPropertyAction("os.name")); - if (os.toUpperCase().startsWith("WINDOWS")) { + if (os.toUpperCase(Locale.ENGLISH).startsWith("WINDOWS")) { Credentials creds = acquireDefaultCreds(); if (creds == null) { if (DEBUG) { diff --git a/jdk/src/share/classes/sun/security/pkcs/PKCS9Attribute.java b/jdk/src/share/classes/sun/security/pkcs/PKCS9Attribute.java index 05b61eb0c32..fb1862f6adb 100644 --- a/jdk/src/share/classes/sun/security/pkcs/PKCS9Attribute.java +++ b/jdk/src/share/classes/sun/security/pkcs/PKCS9Attribute.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,7 @@ package sun.security.pkcs; import java.io.IOException; import java.io.OutputStream; import java.security.cert.CertificateException; +import java.util.Locale; import java.util.Date; import java.util.Hashtable; import sun.security.x509.CertificateExtensions; @@ -742,7 +743,7 @@ public class PKCS9Attribute implements DerEncoder { * the name. */ public static ObjectIdentifier getOID(String name) { - return NAME_OID_TABLE.get(name.toLowerCase()); + return NAME_OID_TABLE.get(name.toLowerCase(Locale.ENGLISH)); } /** diff --git a/jdk/src/share/classes/sun/security/pkcs11/P11Cipher.java b/jdk/src/share/classes/sun/security/pkcs11/P11Cipher.java index cd6731bae2c..1ea39e799d1 100644 --- a/jdk/src/share/classes/sun/security/pkcs11/P11Cipher.java +++ b/jdk/src/share/classes/sun/security/pkcs11/P11Cipher.java @@ -26,6 +26,7 @@ package sun.security.pkcs11; import java.nio.ByteBuffer; import java.util.Arrays; +import java.util.Locale; import java.security.*; import java.security.spec.*; @@ -201,7 +202,7 @@ final class P11Cipher extends CipherSpi { } private int parseMode(String mode) throws NoSuchAlgorithmException { - mode = mode.toUpperCase(); + mode = mode.toUpperCase(Locale.ENGLISH); int result; if (mode.equals("ECB")) { result = MODE_ECB; @@ -222,7 +223,7 @@ final class P11Cipher extends CipherSpi { throws NoSuchPaddingException { paddingObj = null; padBuffer = null; - padding = padding.toUpperCase(); + padding = padding.toUpperCase(Locale.ENGLISH); if (padding.equals("NOPADDING")) { paddingType = PAD_NONE; } else if (padding.equals("PKCS5PADDING")) { diff --git a/jdk/src/share/classes/sun/security/pkcs11/P11RSACipher.java b/jdk/src/share/classes/sun/security/pkcs11/P11RSACipher.java index 7a092df10a1..18f3ab450ef 100644 --- a/jdk/src/share/classes/sun/security/pkcs11/P11RSACipher.java +++ b/jdk/src/share/classes/sun/security/pkcs11/P11RSACipher.java @@ -29,6 +29,8 @@ import java.security.*; import java.security.spec.AlgorithmParameterSpec; import java.security.spec.*; +import java.util.Locale; + import javax.crypto.*; import javax.crypto.spec.*; @@ -110,7 +112,7 @@ final class P11RSACipher extends CipherSpi { protected void engineSetPadding(String padding) throws NoSuchPaddingException { - String lowerPadding = padding.toLowerCase(); + String lowerPadding = padding.toLowerCase(Locale.ENGLISH); if (lowerPadding.equals("pkcs1Padding")) { // empty } else { diff --git a/jdk/src/share/classes/sun/security/provider/certpath/URICertStore.java b/jdk/src/share/classes/sun/security/provider/certpath/URICertStore.java index c0a36b4932a..a27cfa10505 100644 --- a/jdk/src/share/classes/sun/security/provider/certpath/URICertStore.java +++ b/jdk/src/share/classes/sun/security/provider/certpath/URICertStore.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2010 Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -52,6 +52,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.Locale; import sun.security.x509.AccessDescription; import sun.security.x509.GeneralNameInterface; import sun.security.x509.URIName; @@ -162,7 +163,7 @@ class URICertStore extends CertStoreSpi { } this.uri = ((URICertStoreParameters) params).uri; // if ldap URI, use an LDAPCertStore to fetch certs and CRLs - if (uri.getScheme().toLowerCase().equals("ldap")) { + if (uri.getScheme().toLowerCase(Locale.ENGLISH).equals("ldap")) { if (LDAP.helper() == null) throw new NoSuchAlgorithmException("LDAP not present"); ldap = true; diff --git a/jdk/src/share/classes/sun/security/util/Debug.java b/jdk/src/share/classes/sun/security/util/Debug.java index df5585096fc..5701a80cf9f 100644 --- a/jdk/src/share/classes/sun/security/util/Debug.java +++ b/jdk/src/share/classes/sun/security/util/Debug.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,7 @@ package sun.security.util; import java.math.BigInteger; import java.util.regex.Pattern; import java.util.regex.Matcher; +import java.util.Locale; /** * A utility class for debuging. @@ -262,7 +263,7 @@ public class Debug { source = left; // convert the rest to lower-case characters - target.append(source.toString().toLowerCase()); + target.append(source.toString().toLowerCase(Locale.ENGLISH)); return target.toString(); } diff --git a/jdk/src/share/classes/sun/security/x509/AVA.java b/jdk/src/share/classes/sun/security/x509/AVA.java index ce0081523c8..e88947488cc 100644 --- a/jdk/src/share/classes/sun/security/x509/AVA.java +++ b/jdk/src/share/classes/sun/security/x509/AVA.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1227,7 +1227,7 @@ class AVAKeyword { (String keyword, int standard, Map extraKeywordMap) throws IOException { - keyword = keyword.toUpperCase(); + keyword = keyword.toUpperCase(Locale.ENGLISH); if (standard == AVA.RFC2253) { if (keyword.startsWith(" ") || keyword.endsWith(" ")) { throw new IOException("Invalid leading or trailing space " + diff --git a/jdk/src/share/classes/sun/security/x509/AlgorithmId.java b/jdk/src/share/classes/sun/security/x509/AlgorithmId.java index f593304df29..e28c3445718 100644 --- a/jdk/src/share/classes/sun/security/x509/AlgorithmId.java +++ b/jdk/src/share/classes/sun/security/x509/AlgorithmId.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -553,9 +553,10 @@ public class AlgorithmId implements Serializable, DerEncoder { for (Enumeration enum_ = provs[i].keys(); enum_.hasMoreElements(); ) { String alias = (String)enum_.nextElement(); + String upperCaseAlias = alias.toUpperCase(Locale.ENGLISH); int index; - if (alias.toUpperCase().startsWith("ALG.ALIAS") && - (index=alias.toUpperCase().indexOf("OID.", 0)) != -1) { + if (upperCaseAlias.startsWith("ALG.ALIAS") && + (index=upperCaseAlias.indexOf("OID.", 0)) != -1) { index += "OID.".length(); if (index == alias.length()) { // invalid alias entry @@ -565,19 +566,26 @@ public class AlgorithmId implements Serializable, DerEncoder { oidTable = new HashMap(); } oidString = alias.substring(index); - String stdAlgName - = provs[i].getProperty(alias).toUpperCase(); - if (oidTable.get(stdAlgName) == null) { + String stdAlgName = provs[i].getProperty(alias); + if (stdAlgName != null) { + stdAlgName = stdAlgName.toUpperCase(Locale.ENGLISH); + } + if (stdAlgName != null && + oidTable.get(stdAlgName) == null) { oidTable.put(stdAlgName, new ObjectIdentifier(oidString)); } } } } + + if (oidTable == null) { + oidTable = new HashMap(1); + } initOidTable = true; } - return oidTable.get(name.toUpperCase()); + return oidTable.get(name.toUpperCase(Locale.ENGLISH)); } private static ObjectIdentifier oid(int ... values) { diff --git a/jdk/src/share/classes/sun/security/x509/DNSName.java b/jdk/src/share/classes/sun/security/x509/DNSName.java index f0dc6943cb9..398e93fe042 100644 --- a/jdk/src/share/classes/sun/security/x509/DNSName.java +++ b/jdk/src/share/classes/sun/security/x509/DNSName.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2000, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ package sun.security.x509; import java.io.IOException; +import java.util.Locale; import sun.security.util.*; @@ -198,8 +199,9 @@ public class DNSName implements GeneralNameInterface { else if (inputName.getType() != NAME_DNS) constraintType = NAME_DIFF_TYPE; else { - String inName = (((DNSName)inputName).getName()).toLowerCase(); - String thisName = name.toLowerCase(); + String inName = + (((DNSName)inputName).getName()).toLowerCase(Locale.ENGLISH); + String thisName = name.toLowerCase(Locale.ENGLISH); if (inName.equals(thisName)) constraintType = NAME_MATCH; else if (thisName.endsWith(inName)) { diff --git a/jdk/src/share/classes/sun/security/x509/RFC822Name.java b/jdk/src/share/classes/sun/security/x509/RFC822Name.java index 81f6af982fe..8f56903469c 100644 --- a/jdk/src/share/classes/sun/security/x509/RFC822Name.java +++ b/jdk/src/share/classes/sun/security/x509/RFC822Name.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2000, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ package sun.security.x509; import java.io.IOException; +import java.util.Locale; import sun.security.util.*; @@ -187,8 +188,9 @@ public class RFC822Name implements GeneralNameInterface constraintType = NAME_DIFF_TYPE; } else { //RFC2459 specifies that case is not significant in RFC822Names - String inName = (((RFC822Name)inputName).getName()).toLowerCase(); - String thisName = name.toLowerCase(); + String inName = + (((RFC822Name)inputName).getName()).toLowerCase(Locale.ENGLISH); + String thisName = name.toLowerCase(Locale.ENGLISH); if (inName.equals(thisName)) { constraintType = NAME_MATCH; } else if (thisName.endsWith(inName)) { diff --git a/jdk/test/sun/security/x509/AlgorithmId/TurkishRegion.java b/jdk/test/sun/security/x509/AlgorithmId/TurkishRegion.java new file mode 100644 index 00000000000..5ca91e02677 --- /dev/null +++ b/jdk/test/sun/security/x509/AlgorithmId/TurkishRegion.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * 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 6867345 + * @summary Turkish regional options cause NPE in + * sun.security.x509.AlgorithmId.algOID + * @run main/othervm -Duser.language=tr -Duser.region=TR TurkishRegion + * @author Xuelei Fan + */ + +import sun.security.x509.*; + +public class TurkishRegion { + + public static void main(String[] args) throws Exception { + AlgorithmId algId = AlgorithmId.get("PBEWITHMD5ANDDES"); + } +} From 9d92d626e366e0f28055c91676911188a309e95a Mon Sep 17 00:00:00 2001 From: Weijun Wang Date: Mon, 26 Jul 2010 17:21:51 +0800 Subject: [PATCH 25/56] 6972005: ConfPlusProp.java test failure when DNS has info for realm Reviewed-by: xuelei --- jdk/test/sun/security/krb5/ConfPlusProp.java | 6 ++++-- jdk/test/sun/security/krb5/confplusprop.conf | 1 + jdk/test/sun/security/krb5/confplusprop2.conf | 3 +++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/jdk/test/sun/security/krb5/ConfPlusProp.java b/jdk/test/sun/security/krb5/ConfPlusProp.java index f6304a131b0..e29637b1b15 100644 --- a/jdk/test/sun/security/krb5/ConfPlusProp.java +++ b/jdk/test/sun/security/krb5/ConfPlusProp.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. * 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,7 @@ * @test * @bug 6857795 * @bug 6858589 + * @bug 6972005 * @summary krb5.conf ignored if system properties on realm and kdc are provided */ @@ -96,7 +97,8 @@ public class ConfPlusProp { System.setProperty("java.security.krb5.conf", "i-am-not-a file"); refresh(); - checkDefaultRealm(null); + // Default realm might come from DNS + //checkDefaultRealm(null); check("R1", null); check("R2", null); check("R3", null); diff --git a/jdk/test/sun/security/krb5/confplusprop.conf b/jdk/test/sun/security/krb5/confplusprop.conf index 80c925b14cd..5e499483348 100644 --- a/jdk/test/sun/security/krb5/confplusprop.conf +++ b/jdk/test/sun/security/krb5/confplusprop.conf @@ -1,6 +1,7 @@ [libdefaults] default_realm = R1 forwardable = well +dns_lookup_realm = false [realms] R1 = { diff --git a/jdk/test/sun/security/krb5/confplusprop2.conf b/jdk/test/sun/security/krb5/confplusprop2.conf index df00eccbccf..c55464bd846 100644 --- a/jdk/test/sun/security/krb5/confplusprop2.conf +++ b/jdk/test/sun/security/krb5/confplusprop2.conf @@ -1,3 +1,6 @@ +[libdefaults] +dns_lookup_realm = false + [realms] R1 = { kdc = k12 From 564c0a977bc52111cd9738cbc38a3c477be930c9 Mon Sep 17 00:00:00 2001 From: Martin Buchholz Date: Mon, 26 Jul 2010 08:17:50 -0700 Subject: [PATCH 26/56] 6717780: (coll spec) LinkedList api documentation provides the wrong method name Cleanup by simply making Deque equal status with List Reviewed-by: darcy --- jdk/src/share/classes/java/util/LinkedList.java | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/jdk/src/share/classes/java/util/LinkedList.java b/jdk/src/share/classes/java/util/LinkedList.java index 34685d91ca7..9feb95e54ff 100644 --- a/jdk/src/share/classes/java/util/LinkedList.java +++ b/jdk/src/share/classes/java/util/LinkedList.java @@ -26,18 +26,9 @@ package java.util; /** - * Linked list implementation of the {@code List} interface. Implements all - * optional list operations, and permits all elements (including - * {@code null}). In addition to implementing the {@code List} interface, - * the {@code LinkedList} class provides uniformly named methods to - * {@code get}, {@code remove} and {@code insert} an element at the - * beginning and end of the list. These operations allow linked lists to be - * used as a stack, {@linkplain Queue queue}, or {@linkplain Deque - * double-ended queue}. - * - *

    The class implements the {@code Deque} interface, providing - * first-in-first-out queue operations for {@code add}, - * {@code poll}, along with other stack and deque operations. + * Linked list implementation of the {@link List} and {@link Deque} interfaces. + * Implements all optional operations, and permits all elements (including + * {@code null}). * *

    All of the operations perform as could be expected for a doubly-linked * list. Operations that index into the list will traverse the list from From cf3105821b28261c12060abc40320dd1f5649b97 Mon Sep 17 00:00:00 2001 From: "Daniel D. Daugherty" Date: Mon, 26 Jul 2010 09:06:47 -0700 Subject: [PATCH 27/56] 6971847: 4/4 jmap '-histo:live' option is necessary for proper leak detection Add work around for 6971851. Abort if 'histo:live' option isn't supported. Reviewed-by: alanb, darcy --- .../util/logging/AnonLoggerWeakRefLeak.sh | 31 +++++++++++++++++-- .../java/util/logging/LoggerWeakRefLeak.sh | 31 +++++++++++++++++-- 2 files changed, 56 insertions(+), 6 deletions(-) diff --git a/jdk/test/java/util/logging/AnonLoggerWeakRefLeak.sh b/jdk/test/java/util/logging/AnonLoggerWeakRefLeak.sh index 1402881275b..eef8641c7b6 100644 --- a/jdk/test/java/util/logging/AnonLoggerWeakRefLeak.sh +++ b/jdk/test/java/util/logging/AnonLoggerWeakRefLeak.sh @@ -59,9 +59,34 @@ set +e status="$?" set -e if [ "$status" != 0 ]; then - echo "INFO: switching jmap option from '$jmap_option'\c" - jmap_option="-histo" - echo " to '$jmap_option'." + # usage message doesn't show ':live' option + + if $isWindows; then + # If SA isn't present, then jmap gives a different usage message + # that doesn't show the ':live' option. However, that's a bug that + # is covered by 6971851 so we try using the option just to be sure. + # For some reason, this problem has only been seen on OpenJDK6 on + # Windows. Not sure why. + set +e + # Note: Don't copy this code to try probing process 0 on Linux; it + # will kill the process group in strange ways. + "${JMAP}" "$jmap_option" 0 2>&1 | grep 'Usage' > /dev/null 2>&1 + status="$?" + set -e + if [ "$status" = 0 ]; then + # Usage message generated so flag the problem. + status=1 + else + # No usage message so clear the flag. + status=0 + fi + fi + + if [ "$status" != 0 ]; then + echo "ERROR: 'jmap $jmap_option' is not supported so this test" + echo "ERROR: cannot work reliably. Aborting!" + exit 2 + fi fi # Start application and use TEST_NAME.port for coordination diff --git a/jdk/test/java/util/logging/LoggerWeakRefLeak.sh b/jdk/test/java/util/logging/LoggerWeakRefLeak.sh index 200e49b9369..ea3dc1f8f1d 100644 --- a/jdk/test/java/util/logging/LoggerWeakRefLeak.sh +++ b/jdk/test/java/util/logging/LoggerWeakRefLeak.sh @@ -59,9 +59,34 @@ set +e status="$?" set -e if [ "$status" != 0 ]; then - echo "INFO: switching jmap option from '$jmap_option'\c" - jmap_option="-histo" - echo " to '$jmap_option'." + # usage message doesn't show ':live' option + + if $isWindows; then + # If SA isn't present, then jmap gives a different usage message + # that doesn't show the ':live' option. However, that's a bug that + # is covered by 6971851 so we try using the option just to be sure. + # For some reason, this problem has only been seen on OpenJDK6 on + # Windows. Not sure why. + set +e + # Note: Don't copy this code to try probing process 0 on Linux; it + # will kill the process group in strange ways. + "${JMAP}" "$jmap_option" 0 2>&1 | grep 'Usage' > /dev/null 2>&1 + status="$?" + set -e + if [ "$status" = 0 ]; then + # Usage message generated so flag the problem. + status=1 + else + # No usage message so clear the flag. + status=0 + fi + fi + + if [ "$status" != 0 ]; then + echo "ERROR: 'jmap $jmap_option' is not supported so this test" + echo "ERROR: cannot work reliably. Aborting!" + exit 2 + fi fi # Start application and use TEST_NAME.port for coordination From caefa97f8c4625e5eb9ea9f93698b5a17d31e70c Mon Sep 17 00:00:00 2001 From: Xue-Lei Andrew Fan Date: Tue, 27 Jul 2010 16:07:00 +0800 Subject: [PATCH 28/56] 6870947: 15 sec delay detecting "socket closed" condition when a TCP connection is reset by an LDAP server Reviewed-by: weijun --- jdk/src/share/classes/com/sun/jndi/ldap/Connection.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/jdk/src/share/classes/com/sun/jndi/ldap/Connection.java b/jdk/src/share/classes/com/sun/jndi/ldap/Connection.java index 77890393387..4503d261fff 100644 --- a/jdk/src/share/classes/com/sun/jndi/ldap/Connection.java +++ b/jdk/src/share/classes/com/sun/jndi/ldap/Connection.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -658,6 +658,11 @@ public final class Connection implements Runnable { } } if (nparent) { + LdapRequest ldr = pendingRequests; + while (ldr != null) { + ldr.notify(); + ldr = ldr.next; + } parent.processConnectionClosure(); } } From 837cc6d0644f798b32646964a2b214b445d891e6 Mon Sep 17 00:00:00 2001 From: Vinnie Ryan Date: Tue, 27 Jul 2010 11:40:46 +0100 Subject: [PATCH 29/56] 6972409: Cease emitting LDAP filter debug messages Reviewed-by: xuelei --- jdk/src/share/classes/com/sun/jndi/ldap/Filter.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/jdk/src/share/classes/com/sun/jndi/ldap/Filter.java b/jdk/src/share/classes/com/sun/jndi/ldap/Filter.java index b40bdcf6595..626f1f86f95 100644 --- a/jdk/src/share/classes/com/sun/jndi/ldap/Filter.java +++ b/jdk/src/share/classes/com/sun/jndi/ldap/Filter.java @@ -803,8 +803,7 @@ final class Filter { // //////////////////////////////////////////////////////////////////////////// - // private static final boolean dbg = false; - private static final boolean dbg = true; + private static final boolean dbg = false; private static int dbgIndent = 0; private static void dprint(String msg) { From 2d91b17b0a93e8fff4468e860a4f649a4d09a845 Mon Sep 17 00:00:00 2001 From: Chris Hegarty Date: Thu, 29 Jul 2010 10:02:41 +0100 Subject: [PATCH 30/56] 6972374: NetworkInterface.getNetworkInterfaces throws "java.net.SocketException" on Solaris zone Reviewed-by: alanb, dsamersoff --- jdk/src/solaris/native/java/net/NetworkInterface.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/jdk/src/solaris/native/java/net/NetworkInterface.c b/jdk/src/solaris/native/java/net/NetworkInterface.c index eb4b2929dae..c166cc86dda 100644 --- a/jdk/src/solaris/native/java/net/NetworkInterface.c +++ b/jdk/src/solaris/native/java/net/NetworkInterface.c @@ -131,7 +131,7 @@ static struct sockaddr *getBroadcast(JNIEnv *env, int sock, const char *name, s static short getSubnet(JNIEnv *env, int sock, const char *ifname); static int getIndex(int sock, const char *ifname); -static int getFlags(JNIEnv *env, int sock, const char *ifname); +static int getFlags(int sock, const char *ifname); static int getMacAddress(JNIEnv *env, int sock, const char* ifname, const struct in_addr* addr, unsigned char *buf); static int getMTU(JNIEnv *env, int sock, const char *ifname); @@ -550,7 +550,7 @@ static int getFlags0(JNIEnv *env, jstring name) { name_utf = (*env)->GetStringUTFChars(env, name, &isCopy); - ret = getFlags(env, sock, name_utf); + ret = getFlags(sock, name_utf); close(sock); (*env)->ReleaseStringUTFChars(env, name, name_utf); @@ -885,7 +885,7 @@ netif *addif(JNIEnv *env, int sock, const char * if_name, netif *ifs, struct soc * the 'parent' interface with the new records. */ *name_colonP = 0; - if (getFlags(env,sock,name) < 0) { + if (getFlags(sock, name) < 0) { // failed to access parent interface do not create parent. // We are a virtual interface with no parent. isVirtual = 1; @@ -1257,7 +1257,7 @@ static int getMTU(JNIEnv *env, int sock, const char *ifname) { return if2.ifr_mtu; } -static int getFlags(JNIEnv *env, int sock, const char *ifname) { +static int getFlags(int sock, const char *ifname) { struct ifreq if2; int ret = -1; @@ -1633,13 +1633,12 @@ static int getMTU(JNIEnv *env, int sock, const char *ifname) { } -static int getFlags(JNIEnv *env, int sock, const char *ifname) { +static int getFlags(int sock, const char *ifname) { struct lifreq lifr; memset((caddr_t)&lifr, 0, sizeof(lifr)); strcpy((caddr_t)&(lifr.lifr_name), ifname); if (ioctl(sock, SIOCGLIFFLAGS, (char *)&lifr) < 0) { - NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGLIFFLAGS failed"); return -1; } From 1736731b74bd51b788a6d04e0346136f98633342 Mon Sep 17 00:00:00 2001 From: Alan Bateman Date: Thu, 29 Jul 2010 13:08:58 +0100 Subject: [PATCH 31/56] 6934977: (bf) MappedByteBuffer.load can SIGBUS if file is truncated 6799037: (fs) MappedByteBuffer.load crash with unaligned file-mapping (sol) Reviewed-by: chegar, forax --- jdk/src/share/classes/java/nio/Bits.java | 3 + .../classes/java/nio/MappedByteBuffer.java | 48 ++++++++-- .../native/java/nio/MappedByteBuffer.c | 41 +++----- .../native/java/nio/MappedByteBuffer.c | 21 +---- jdk/test/java/nio/MappedByteBuffer/Basic.java | 8 +- .../java/nio/MappedByteBuffer/Truncate.java | 94 +++++++++++++++++++ 6 files changed, 163 insertions(+), 52 deletions(-) create mode 100644 jdk/test/java/nio/MappedByteBuffer/Truncate.java diff --git a/jdk/src/share/classes/java/nio/Bits.java b/jdk/src/share/classes/java/nio/Bits.java index 4adf3e48066..fa11b6be785 100644 --- a/jdk/src/share/classes/java/nio/Bits.java +++ b/jdk/src/share/classes/java/nio/Bits.java @@ -596,6 +596,9 @@ class Bits { // package-private return pageSize; } + static int pageCount(long size) { + return (int)(size + (long)pageSize() - 1L) / pageSize(); + } private static boolean unaligned; private static boolean unalignedKnown = false; diff --git a/jdk/src/share/classes/java/nio/MappedByteBuffer.java b/jdk/src/share/classes/java/nio/MappedByteBuffer.java index 7e415c67bca..4811f41d2e1 100644 --- a/jdk/src/share/classes/java/nio/MappedByteBuffer.java +++ b/jdk/src/share/classes/java/nio/MappedByteBuffer.java @@ -25,6 +25,8 @@ package java.nio; +import sun.misc.Unsafe; + /** * A direct byte buffer whose content is a memory-mapped region of a file. @@ -93,6 +95,22 @@ public abstract class MappedByteBuffer throw new UnsupportedOperationException(); } + // Returns the distance (in bytes) of the buffer from the page aligned address + // of the mapping. Computed each time to avoid storing in every direct buffer. + private long mappingOffset() { + int ps = Bits.pageSize(); + long offset = address % ps; + return (offset >= 0) ? offset : (ps + offset); + } + + private long mappingAddress(long mappingOffset) { + return address - mappingOffset; + } + + private long mappingLength(long mappingOffset) { + return (long)capacity() + mappingOffset; + } + /** * Tells whether or not this buffer's content is resident in physical * memory. @@ -115,7 +133,9 @@ public abstract class MappedByteBuffer checkMapped(); if ((address == 0) || (capacity() == 0)) return true; - return isLoaded0(((DirectByteBuffer)this).address(), capacity()); + long offset = mappingOffset(); + long length = mappingLength(offset); + return isLoaded0(mappingAddress(offset), length, Bits.pageCount(length)); } /** @@ -132,7 +152,20 @@ public abstract class MappedByteBuffer checkMapped(); if ((address == 0) || (capacity() == 0)) return this; - load0(((DirectByteBuffer)this).address(), capacity(), Bits.pageSize()); + long offset = mappingOffset(); + long length = mappingLength(offset); + load0(mappingAddress(offset), length); + + // touch each page + Unsafe unsafe = Unsafe.getUnsafe(); + int ps = Bits.pageSize(); + int count = Bits.pageCount(length); + long a = mappingAddress(offset); + for (int i=0; i #include - JNIEXPORT jboolean JNICALL -Java_java_nio_MappedByteBuffer_isLoaded0(JNIEnv *env, jobject obj, - jlong address, jlong len) +Java_java_nio_MappedByteBuffer_isLoaded0(JNIEnv *env, jobject obj, jlong address, + jlong len, jint numPages) { jboolean loaded = JNI_TRUE; - jint pageSize = sysconf(_SC_PAGESIZE); - jint numPages = (len + pageSize - 1) / pageSize; int result = 0; int i = 0; void *a = (void *) jlong_to_ptr(address); @@ -55,9 +52,9 @@ Java_java_nio_MappedByteBuffer_isLoaded0(JNIEnv *env, jobject obj, } result = mincore(a, (size_t)len, vec); - if (result != 0) { - free(vec); + if (result == -1) { JNU_ThrowIOExceptionWithLastError(env, "mincore failed"); + free(vec); return JNI_FALSE; } @@ -72,23 +69,15 @@ Java_java_nio_MappedByteBuffer_isLoaded0(JNIEnv *env, jobject obj, } -JNIEXPORT jint JNICALL +JNIEXPORT void JNICALL Java_java_nio_MappedByteBuffer_load0(JNIEnv *env, jobject obj, jlong address, - jlong len, jint pageSize) + jlong len) { - int pageIncrement = pageSize / sizeof(int); - int numPages = (len + pageSize - 1) / pageSize; - int *ptr = (int *)jlong_to_ptr(address); - int i = 0; - int j = 0; - int result = madvise((caddr_t)ptr, len, MADV_WILLNEED); - - /* touch every page */ - for (i=0; i JNIEXPORT jboolean JNICALL -Java_java_nio_MappedByteBuffer_isLoaded0(JNIEnv *env, jobject obj, - jlong address, jlong len) +Java_java_nio_MappedByteBuffer_isLoaded0(JNIEnv *env, jobject obj, jlong address, + jlong len, jint numPages) { jboolean loaded = JNI_FALSE; /* Information not available? @@ -43,22 +43,11 @@ Java_java_nio_MappedByteBuffer_isLoaded0(JNIEnv *env, jobject obj, return loaded; } -JNIEXPORT jint JNICALL +JNIEXPORT void JNICALL Java_java_nio_MappedByteBuffer_load0(JNIEnv *env, jobject obj, jlong address, - jlong len, jint pageSize) + jlong len) { - int *ptr = (int *) jlong_to_ptr(address); - int pageIncrement = pageSize / sizeof(int); - jlong numPages = (len + pageSize - 1) / pageSize; - int i = 0; - int j = 0; - - /* touch every page */ - for (i=0; i() { + public Void call() { + mbb.get((int)TRUNCATED_FILE_SIZE + 1); + mbb.put((int)TRUNCATED_FILE_SIZE + 2, (byte)123); + return null; + } + }); + // Test 2: load buffer into memory + execute(new Callable() { + public Void call() throws IOException { + mbb.load(); + return null; + } + }); + } + fc.close(); + } + + // Runs the given task in its own thread. If operating correcting the + // the thread will terminate with an InternalError as the mapped buffer + // is inaccessible. + static void execute(final Callable c) { + Runnable r = new Runnable() { + public void run() { + try { + Object ignore = c.call(); + } catch (Exception ignore) { + } + } + }; + Thread t = new Thread(r); + t.start(); + try { t.join(); } catch (InterruptedException ignore) { } + } +} From 476f58c4af0201917ec4ea4065db5761a94fdb21 Mon Sep 17 00:00:00 2001 From: Alexander Potochkin Date: Thu, 29 Jul 2010 19:34:03 +0400 Subject: [PATCH 32/56] 4743225: Size of JComboBox list is wrong when list is populated via PopupMenuListener Reviewed-by: rupashka --- .../swing/plaf/basic/BasicComboPopup.java | 5 +- .../swing/JComboBox/4743225/bug4743225.java | 111 ++++++++++++++++++ 2 files changed, 114 insertions(+), 2 deletions(-) create mode 100644 jdk/test/javax/swing/JComboBox/4743225/bug4743225.java diff --git a/jdk/src/share/classes/javax/swing/plaf/basic/BasicComboPopup.java b/jdk/src/share/classes/javax/swing/plaf/basic/BasicComboPopup.java index 077c15b9d4a..803e4d01bda 100644 --- a/jdk/src/share/classes/javax/swing/plaf/basic/BasicComboPopup.java +++ b/jdk/src/share/classes/javax/swing/plaf/basic/BasicComboPopup.java @@ -202,8 +202,8 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup { * Implementation of ComboPopup.show(). */ public void show() { + comboBox.firePopupMenuWillBecomeVisible(); setListSelection(comboBox.getSelectedIndex()); - Point location = getPopupLocation(); show( comboBox, location.x, location.y ); } @@ -344,7 +344,8 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup { protected void firePopupMenuWillBecomeVisible() { super.firePopupMenuWillBecomeVisible(); - comboBox.firePopupMenuWillBecomeVisible(); + // comboBox.firePopupMenuWillBecomeVisible() is called from BasicComboPopup.show() method + // to let the user change the popup menu from the PopupMenuListener.popupMenuWillBecomeVisible() } protected void firePopupMenuWillBecomeInvisible() { diff --git a/jdk/test/javax/swing/JComboBox/4743225/bug4743225.java b/jdk/test/javax/swing/JComboBox/4743225/bug4743225.java new file mode 100644 index 00000000000..2a41b3075ac --- /dev/null +++ b/jdk/test/javax/swing/JComboBox/4743225/bug4743225.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * 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 4743225 + * @summary Size of JComboBox list is wrong when list is populated via PopupMenuListener + * @author Alexander Potochkin + */ + +import sun.awt.SunToolkit; + +import javax.accessibility.AccessibleContext; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.SwingUtilities; +import javax.swing.event.PopupMenuEvent; +import javax.swing.event.PopupMenuListener; +import javax.swing.plaf.basic.BasicComboPopup; +import java.awt.FlowLayout; +import java.awt.Point; +import java.awt.Robot; +import java.awt.Toolkit; +import java.awt.event.InputEvent; + +public class bug4743225 extends JFrame { + + private static JComboBox cb; + private static volatile boolean flag; + + public bug4743225() { + setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + setLayout(new FlowLayout()); + cb = new JComboBox(new Object[] {"one", "two", "three"}); + cb.addPopupMenuListener(new PopupMenuListener() { + public void popupMenuWillBecomeVisible(PopupMenuEvent e) { + cb.addItem("Test"); + } + + public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { + } + + public void popupMenuCanceled(PopupMenuEvent e) { + } + }); + add(cb); + pack(); + } + + public static BasicComboPopup getPopup() { + AccessibleContext c = cb.getAccessibleContext(); + for(int i = 0; i < c.getAccessibleChildrenCount(); i ++) { + if (c.getAccessibleChild(i) instanceof BasicComboPopup) { + return (BasicComboPopup) c.getAccessibleChild(i); + } + } + throw new AssertionError("No BasicComboPopup found"); + } + + public static void main(String... args) throws Exception { + + Robot robot = new Robot(); + robot.setAutoDelay(20); + SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit(); + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + new bug4743225().setVisible(true); + } + }); + toolkit.realSync(); + + // calling this method from main thread is ok + Point point = cb.getLocationOnScreen(); + robot.mouseMove(point.x + 10, point.y + 10); + robot.mousePress(InputEvent.BUTTON1_MASK); + robot.mouseRelease(InputEvent.BUTTON1_MASK); + toolkit.realSync(); + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + if(getPopup().getList().getLastVisibleIndex() == 3) { + flag = true; + } + } + }); + + if (!flag) { + throw new RuntimeException("The ComboBox popup wasn't correctly updated"); + } + } +} From c0563bc803f942bd3f5b1d5ac5069b75f31e4e45 Mon Sep 17 00:00:00 2001 From: Christine Lu Date: Thu, 29 Jul 2010 13:33:02 -0700 Subject: [PATCH 33/56] Added tag jdk7-b103 for changeset a80a6daf6891 --- .hgtags-top-repo | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags-top-repo b/.hgtags-top-repo index 95f8b4a541a..8b24549198a 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -77,3 +77,4 @@ e7f18db469a3e947b7096bfd12e87380e5a042cd jdk7-b99 b218a53ec7d3d42be61d31d6917a6c5c037b6f56 jdk7-b100 4193eaf5f1b82794c6a0fb1a8d11af43d1b1d611 jdk7-b101 a136a51f5113da4dad3853b74a8536ab583ab112 jdk7-b102 +be2aedc4e3b1751c1310f334242ba69e90867f38 jdk7-b103 From e6fcfd056b55982cc8aabfd4aa2af7c0742d3877 Mon Sep 17 00:00:00 2001 From: Christine Lu Date: Thu, 29 Jul 2010 13:33:04 -0700 Subject: [PATCH 34/56] Added tag jdk7-b103 for changeset a5f45610331b --- corba/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/corba/.hgtags b/corba/.hgtags index 81316616c47..4bf02cd1192 100644 --- a/corba/.hgtags +++ b/corba/.hgtags @@ -77,3 +77,4 @@ edc2a2659c77dabc55cb55bb617bad89e3a05bb3 jdk7-b96 a56d734a1e970e1a21a8f4feb13053e9a33674c7 jdk7-b100 86a239832646a74811695428984b6947c0bd6dc8 jdk7-b101 78561a95779090b5106c8d0f1a75360a027ef087 jdk7-b102 +11e7678c3eb169b77d9a9892fe5e3dfa1d1a0d51 jdk7-b103 From 5bc757e86c2519ac5f3f5163e636e511b3a99155 Mon Sep 17 00:00:00 2001 From: Christine Lu Date: Thu, 29 Jul 2010 13:33:08 -0700 Subject: [PATCH 35/56] Added tag jdk7-b103 for changeset 0dc48f97ffd1 --- hotspot/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/.hgtags b/hotspot/.hgtags index 3d13f93a4be..4c1846c7f6d 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -107,3 +107,4 @@ ad1977f08c4d69162a0775fe3f9576b9fd521d10 jdk7-b100 6c3a919105b68c15b7db923ec9a00006e9560910 jdk7-b101 ad1977f08c4d69162a0775fe3f9576b9fd521d10 hs19-b03 c5cadf1a07717955cf60dbaec16e35b529fd2cb0 jdk7-b102 +cb4250ef73b21de6c487ea14e2b0b99eed67b4b6 jdk7-b103 From a1e95a3802978cb690d01af7f8750e452a2eeef6 Mon Sep 17 00:00:00 2001 From: Christine Lu Date: Thu, 29 Jul 2010 13:33:13 -0700 Subject: [PATCH 36/56] Added tag jdk7-b103 for changeset d599ee7032ef --- jaxp/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jaxp/.hgtags b/jaxp/.hgtags index 7aae73ac3d2..f8021c1f405 100644 --- a/jaxp/.hgtags +++ b/jaxp/.hgtags @@ -77,3 +77,4 @@ d4adf4f2d14c7b79df0a81de884b6b57c6850802 jdk7-b98 d524be5ef62e8b8cb890c59a5d2c19ef0ab50d45 jdk7-b100 17f62a566a2020fd908e77106ed885e0c4e7c14d jdk7-b101 15573625af97d01c4e24549041cba7584da7fe88 jdk7-b102 +b7722e8788644507c10bb69a137de422d0300b24 jdk7-b103 From 9b19c5b40c9534d2cd4440785187fc2c05a0d2c2 Mon Sep 17 00:00:00 2001 From: Christine Lu Date: Thu, 29 Jul 2010 13:33:13 -0700 Subject: [PATCH 37/56] Added tag jdk7-b103 for changeset f84fd6d66187 --- jaxws/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jaxws/.hgtags b/jaxws/.hgtags index f65a239c30b..c0011497e64 100644 --- a/jaxws/.hgtags +++ b/jaxws/.hgtags @@ -77,3 +77,4 @@ dac23846092ad4956ed41b5278f8686476ae46ef jdk7-b97 bd26d0ce0c3cb43e58a8e2770cc03f26d96ffe5c jdk7-b100 b55ce274490082712f5e002b38d2eed505ca863d jdk7-b101 d8580443d1815d68e0035a0560634e50fa899288 jdk7-b102 +267386d6b923f724309cab855a555e2d86a15c8f jdk7-b103 From 2c09c3cf0bdfa0fe5b67df135954a6e94253addc Mon Sep 17 00:00:00 2001 From: Christine Lu Date: Thu, 29 Jul 2010 13:33:20 -0700 Subject: [PATCH 38/56] Added tag jdk7-b103 for changeset 81a799b11c0e --- jdk/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jdk/.hgtags b/jdk/.hgtags index 986d9916659..b21fc77da96 100644 --- a/jdk/.hgtags +++ b/jdk/.hgtags @@ -77,3 +77,4 @@ b1903d7528d33b521df42bc9291bdcdd2f444a29 jdk7-b97 820b4e843d5168370a3bf166d19751a3271d8575 jdk7-b100 d58354a69011f3d3354765fa3167567c4c4a9612 jdk7-b101 13029a61b16bec06535d4f0aa98229b358684128 jdk7-b102 +6488b70a23cc6dc4b7e00809bc503c2884bafb28 jdk7-b103 From f5bf509c49ca942e2ed7870843ca8ade47ce75d2 Mon Sep 17 00:00:00 2001 From: Christine Lu Date: Thu, 29 Jul 2010 13:33:32 -0700 Subject: [PATCH 39/56] Added tag jdk7-b103 for changeset a5cf09e6c109 --- langtools/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/langtools/.hgtags b/langtools/.hgtags index f21369ccd0e..b98711d8c25 100644 --- a/langtools/.hgtags +++ b/langtools/.hgtags @@ -77,3 +77,4 @@ c0a41294297ed397098dd92b647f481f0e1bb8fa jdk7-b97 d1d7595fa824925651f09b8ffcb86c9cf39807be jdk7-b100 20a8fe72ee7b673f59c319a5222fe0eebbd92082 jdk7-b101 ff9c0a0bf7edf637a7dac5062b920924536ed79c jdk7-b102 +bd85271c580ce4600b1b2d5598daa19d02174cf7 jdk7-b103 From 4ce3f156ec366373126fe4bbec0c3faa24083abe Mon Sep 17 00:00:00 2001 From: Erik Trimble Date: Fri, 30 Jul 2010 06:56:40 -0700 Subject: [PATCH 40/56] 6973381: Bump the HS19 build number to 05 Update the HS19 build number to 05 Reviewed-by: jcoomes --- hotspot/make/hotspot_version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotspot/make/hotspot_version b/hotspot/make/hotspot_version index 170bf0414cc..e2f63f0f86c 100644 --- a/hotspot/make/hotspot_version +++ b/hotspot/make/hotspot_version @@ -35,7 +35,7 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2010 HS_MAJOR_VER=19 HS_MINOR_VER=0 -HS_BUILD_NUMBER=04 +HS_BUILD_NUMBER=05 JDK_MAJOR_VER=1 JDK_MINOR_VER=7 From d3b90b4164341cdc9841caf70cdbb5bec9107774 Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Fri, 30 Jul 2010 19:21:27 +0400 Subject: [PATCH 41/56] 6199676: REGRESSION: ColorChooser loses preview when change LandF in Java5 Reviewed-by: alexp, peterz --- .../swing/plaf/basic/BasicColorChooserUI.java | 62 +++++----- .../swing/JColorChooser/Test6199676.java | 117 ++++++++++++++++++ 2 files changed, 148 insertions(+), 31 deletions(-) create mode 100644 jdk/test/javax/swing/JColorChooser/Test6199676.java diff --git a/jdk/src/share/classes/javax/swing/plaf/basic/BasicColorChooserUI.java b/jdk/src/share/classes/javax/swing/plaf/basic/BasicColorChooserUI.java index acd141c1c4a..f8c163d5d2d 100644 --- a/jdk/src/share/classes/javax/swing/plaf/basic/BasicColorChooserUI.java +++ b/jdk/src/share/classes/javax/swing/plaf/basic/BasicColorChooserUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -113,7 +113,6 @@ public class BasicColorChooserUI extends ColorChooserUI previewPanelHolder.setBorder(new TitledBorder(previewString)); } previewPanelHolder.setInheritsPopupMenu(true); - chooser.add(previewPanelHolder, BorderLayout.SOUTH); installPreviewPanel(); chooser.applyComponentOrientation(c.getComponentOrientation()); @@ -126,13 +125,9 @@ public class BasicColorChooserUI extends ColorChooserUI uninstallDefaultChoosers(); uninstallListeners(); + uninstallPreviewPanel(); uninstallDefaults(); - previewPanelHolder.remove(previewPanel); - if (previewPanel instanceof UIResource) { - chooser.setPreviewPanel(null); - } - previewPanelHolder = null; previewPanel = null; defaultChoosers = null; @@ -143,29 +138,37 @@ public class BasicColorChooserUI extends ColorChooserUI } protected void installPreviewPanel() { - if (previewPanel != null) { - previewPanelHolder.remove(previewPanel); - previewPanel.removeMouseListener(getHandler()); + JComponent previewPanel = this.chooser.getPreviewPanel(); + if (previewPanel == null) { + previewPanel = ColorChooserComponentFactory.getPreviewPanel(); } - - previewPanel = chooser.getPreviewPanel(); - Dimension layoutSize = new Dimension(); // fix for bug 4759306 - if (previewPanel != null) { - layoutSize = new BorderLayout().minimumLayoutSize(previewPanel); - if ((previewPanelHolder != null) && (chooser != null) && - (layoutSize.getWidth() + layoutSize.getHeight() == 0)) { - chooser.remove(previewPanelHolder); - return; + else { + Dimension size = new BorderLayout().minimumLayoutSize(previewPanel); + if ((size.width == 0) && (size.height == 0)) { + previewPanel = null; } } - if (previewPanel == null || previewPanel instanceof UIResource) { - previewPanel = ColorChooserComponentFactory.getPreviewPanel(); // get from table? - chooser.setPreviewPanel(previewPanel); + this.previewPanel = previewPanel; + if (previewPanel != null) { + chooser.add(previewPanelHolder, BorderLayout.SOUTH); + previewPanel.setForeground(chooser.getColor()); + previewPanelHolder.add(previewPanel); + previewPanel.addMouseListener(getHandler()); + previewPanel.setInheritsPopupMenu(true); } - previewPanel.setForeground(chooser.getColor()); - previewPanelHolder.add(previewPanel); - previewPanel.addMouseListener(getHandler()); - previewPanel.setInheritsPopupMenu(true); + } + + /** + * Removes installed preview panel from the UI delegate. + * + * @since 1.7 + */ + protected void uninstallPreviewPanel() { + if (this.previewPanel != null) { + this.previewPanel.removeMouseListener(getHandler()); + this.previewPanelHolder.remove(this.previewPanel); + } + this.chooser.remove(this.previewPanelHolder); } protected void installDefaults() { @@ -209,7 +212,6 @@ public class BasicColorChooserUI extends ColorChooserUI chooser.removePropertyChangeListener( propertyChangeListener ); chooser.getSelectionModel().removeChangeListener(previewListener); previewListener = null; - previewPanel.removeMouseListener(getHandler()); } private void selectionChanged(ColorSelectionModel model) { @@ -312,9 +314,8 @@ public class BasicColorChooserUI extends ColorChooserUI } } else if (prop == JColorChooser.PREVIEW_PANEL_PROPERTY) { - if (evt.getNewValue() != previewPanel) { - installPreviewPanel(); - } + uninstallPreviewPanel(); + installPreviewPanel(); } else if (prop == JColorChooser.SELECTION_MODEL_PROPERTY) { ColorSelectionModel oldModel = (ColorSelectionModel) evt.getOldValue(); @@ -352,5 +353,4 @@ public class BasicColorChooserUI extends ColorChooserUI super("color"); } } - } diff --git a/jdk/test/javax/swing/JColorChooser/Test6199676.java b/jdk/test/javax/swing/JColorChooser/Test6199676.java new file mode 100644 index 00000000000..19bb68b4900 --- /dev/null +++ b/jdk/test/javax/swing/JColorChooser/Test6199676.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * 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 6199676 + * @summary Tests preview panel after L&F changing + * @author Sergey Malenkov + */ + +import java.awt.Component; +import java.awt.Container; +import javax.swing.JColorChooser; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.UIManager.LookAndFeelInfo; + +public class Test6199676 implements Runnable { + public static void main(String[] args) { + SwingUtilities.invokeLater(new Test6199676()); + } + + private static void exit(String error) { + if (error != null) { + System.err.println(error); + System.exit(1); + } + else { + System.exit(0); + } + } + + private static Component getPreview(Container container) { + String name = "ColorChooser.previewPanelHolder"; + for (Component component : container.getComponents()) { + if (!name.equals(component.getName())) { + component = (component instanceof Container) + ? getPreview((Container) component) + : null; + } + if (component instanceof Container) { + container = (Container) component; + return 1 == container.getComponentCount() + ? container.getComponent(0) + : null; + } + } + return null; + } + + private static boolean isShowing(Component component) { + return (component != null) && component.isShowing(); + } + + private int index; + private boolean updated; + private JColorChooser chooser; + + public synchronized void run() { + if (this.chooser == null) { + this.chooser = new JColorChooser(); + + JFrame frame = new JFrame(getClass().getName()); + frame.add(this.chooser); + frame.setVisible(true); + } + else if (this.updated) { + if (isShowing(this.chooser.getPreviewPanel())) { + exit("custom preview panel is showing"); + } + exit(null); + } + else { + Component component = this.chooser.getPreviewPanel(); + if (component == null) { + component = getPreview(this.chooser); + } + if (!isShowing(component)) { + exit("default preview panel is not showing"); + } + this.updated = true; + this.chooser.setPreviewPanel(new JPanel()); + } + LookAndFeelInfo[] infos = UIManager.getInstalledLookAndFeels(); + LookAndFeelInfo info = infos[++this.index % infos.length]; + try { + UIManager.setLookAndFeel(info.getClassName()); + } + catch (Exception exception) { + exit("could not change L&F"); + } + SwingUtilities.updateComponentTreeUI(this.chooser); + SwingUtilities.invokeLater(this); + } +} From e51e3b724f337254d8065fd690b9e8ad000088c0 Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Fri, 30 Jul 2010 19:40:29 +0400 Subject: [PATCH 42/56] 6972468: Security manager should be used for tests in java/beans/XMLEncoder Reviewed-by: peterz --- jdk/test/java/beans/XMLEncoder/Test4631471.java | 10 ++++++++-- jdk/test/java/beans/XMLEncoder/Test4903007.java | 6 +++--- .../beans/XMLEncoder/javax_swing_JLayeredPane.java | 6 +++--- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/jdk/test/java/beans/XMLEncoder/Test4631471.java b/jdk/test/java/beans/XMLEncoder/Test4631471.java index 9c67e60e3d9..0b3b107f7c6 100644 --- a/jdk/test/java/beans/XMLEncoder/Test4631471.java +++ b/jdk/test/java/beans/XMLEncoder/Test4631471.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 4631471 + * @bug 4631471 6972468 * @summary Tests DefaultTreeModel encoding * @author Sergey Malenkov, Mark Davidson */ @@ -37,6 +37,12 @@ import javax.swing.tree.TreeNode; public abstract class Test4631471 extends AbstractTest { public static void main(String[] args) throws Exception { + main(); + System.setSecurityManager(new SecurityManager()); + main(); + } + + private static void main() throws Exception { // the DefaultMutableTreeNode will archive correctly new Test4631471() { protected Object getObject() { diff --git a/jdk/test/java/beans/XMLEncoder/Test4903007.java b/jdk/test/java/beans/XMLEncoder/Test4903007.java index 82583720934..02ba9a6a939 100644 --- a/jdk/test/java/beans/XMLEncoder/Test4903007.java +++ b/jdk/test/java/beans/XMLEncoder/Test4903007.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 4903007 + * @bug 4903007 6972468 * @summary Tests encoding of container with boxes and BoxLayout * @author Sergey Malenkov, Mark Davidson */ @@ -36,7 +36,7 @@ import javax.swing.JPanel; public class Test4903007 extends AbstractTest { public static void main(String[] args) throws Exception { - new Test4903007().test(false); // TODO: could not encode with security manager + new Test4903007().test(true); } protected JPanel getObject() { diff --git a/jdk/test/java/beans/XMLEncoder/javax_swing_JLayeredPane.java b/jdk/test/java/beans/XMLEncoder/javax_swing_JLayeredPane.java index 05c90ba15dc..1e41bc41e7b 100644 --- a/jdk/test/java/beans/XMLEncoder/javax_swing_JLayeredPane.java +++ b/jdk/test/java/beans/XMLEncoder/javax_swing_JLayeredPane.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 5023552 + * @bug 5023552 6972468 * @summary Tests JLayeredPane encoding * @author Sergey Malenkov */ @@ -35,7 +35,7 @@ import javax.swing.JPanel; public final class javax_swing_JLayeredPane extends AbstractTest { public static void main(String[] args) { - new javax_swing_JLayeredPane().test(false); // TODO: could not encode with security manager + new javax_swing_JLayeredPane().test(true); } private static void init(JLayeredPane pane, int layer, int x, int y, int w, int h, Color color) { From bf106fcab7ea741c4063ad7d0bcd8b85082fd603 Mon Sep 17 00:00:00 2001 From: Michael McMahon Date: Fri, 30 Jul 2010 18:16:30 +0100 Subject: [PATCH 43/56] 6510892: com/sun/net/httpserver/bugs/B6361557.java fails Reviewed-by: chegar --- .../com/sun/net/httpserver/bugs/B6361557.java | 68 +++++++++++++------ 1 file changed, 48 insertions(+), 20 deletions(-) diff --git a/jdk/test/com/sun/net/httpserver/bugs/B6361557.java b/jdk/test/com/sun/net/httpserver/bugs/B6361557.java index 069db08937b..a1beb7a82d9 100644 --- a/jdk/test/com/sun/net/httpserver/bugs/B6361557.java +++ b/jdk/test/com/sun/net/httpserver/bugs/B6361557.java @@ -24,6 +24,7 @@ /** * @test * @bug 6361557 + * @run main/othervm B6361557 * @summary Lightweight HTTP server quickly runs out of file descriptors on Linux */ @@ -63,6 +64,9 @@ public class B6361557 { } } + final static String request = "GET /test/foo.html HTTP/1.1\r\nContent-length: 0\r\n\r\n"; + final static ByteBuffer requestBuf = ByteBuffer.allocate(64).put(request.getBytes()); + public static void main (String[] args) throws Exception { Handler handler = new Handler(); InetSocketAddress addr = new InetSocketAddress (0); @@ -73,48 +77,72 @@ public class B6361557 { server.setExecutor (executor); server.start (); - ByteBuffer buf = ByteBuffer.allocate (4096); InetSocketAddress destaddr = new InetSocketAddress ( "127.0.0.1", server.getAddress().getPort() ); System.out.println ("destaddr " + destaddr); Selector selector = Selector.open (); - int i = 0; + int requests = 0; + int responses = 0; while (true) { - i ++; int selres = selector.select (1); Set selkeys = selector.selectedKeys(); for (SelectionKey key : selkeys) { if (key.isReadable()) { SocketChannel chan = (SocketChannel)key.channel(); - buf.clear(); + ByteBuffer buf = (ByteBuffer)key.attachment(); try { - int x = chan.read (buf); - if (x == -1) { + int x = chan.read(buf); + if (x == -1 || responseComplete(buf)) { + key.attach(null); chan.close(); + responses++; } } catch (IOException e) {} } } - if (i< NUM) { - SocketChannel schan = SocketChannel.open (destaddr); - String cmd = "GET /test/foo.html HTTP/1.1\r\nContent-length: 0\r\n\r\n"; - buf.rewind (); - buf.put (cmd.getBytes()); - buf.flip(); + if (requests < NUM) { + SocketChannel schan = SocketChannel.open(destaddr); + requestBuf.rewind(); int c = 0; - while (buf.remaining() > 0) { - c += schan.write (buf); + while (requestBuf.remaining() > 0) { + c += schan.write(requestBuf); } - schan.configureBlocking (false); - schan.register (selector, SelectionKey.OP_READ, null); - } else { + schan.configureBlocking(false); + schan.register(selector, SelectionKey.OP_READ, ByteBuffer.allocate(100)); + requests++; + } + if (responses == NUM) { System.out.println ("Finished clients"); - server.stop (1); - executor.shutdown (); - return; + break; } } + server.stop (1); + selector.close(); + executor.shutdown (); + + } + + /* Look for CR LF CR LF */ + static boolean responseComplete(ByteBuffer buf) { + int pos = buf.position(); + buf.flip(); + byte[] lookingFor = new byte[] {'\r', '\n', '\r', '\n' }; + int lookingForCount = 0; + while (buf.hasRemaining()) { + byte b = buf.get(); + if (b == lookingFor[lookingForCount]) { + lookingForCount++; + if (lookingForCount == 4) { + return true; + } + } else { + lookingForCount = 0; + } + } + buf.position(pos); + buf.limit(buf.capacity()); + return false; } } From f6c415404382da9bcdd904c517653df6bcc1c810 Mon Sep 17 00:00:00 2001 From: Kelly O'Hair Date: Mon, 2 Aug 2010 16:31:26 -0700 Subject: [PATCH 44/56] 6973616: Update minimum boot jdk from 1.5 to 1.6 Reviewed-by: igor, jjg --- jdk/make/common/shared/Defs-versions.gmk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdk/make/common/shared/Defs-versions.gmk b/jdk/make/common/shared/Defs-versions.gmk index 327f3a49b01..870ae229f3b 100644 --- a/jdk/make/common/shared/Defs-versions.gmk +++ b/jdk/make/common/shared/Defs-versions.gmk @@ -191,7 +191,7 @@ endif # Generic REQUIRED_ANT_VER = 1.6.3 -REQUIRED_BOOT_VER = 1.5 +REQUIRED_BOOT_VER = 1.6 REQUIRED_FREETYPE_VERSION = 2.3.0 REQUIRED_MAKE_VER = 3.78 REQUIRED_UNZIP_VER = 5.12 From a656854b1ec980cb7b4cd05512dc2a8ab811b621 Mon Sep 17 00:00:00 2001 From: Kelly O'Hair Date: Mon, 2 Aug 2010 16:31:55 -0700 Subject: [PATCH 45/56] 6971426: jdk/make/docs docs target does not work on windows Reviewed-by: igor, jjg --- jdk/make/docs/Makefile | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/jdk/make/docs/Makefile b/jdk/make/docs/Makefile index 20150c81a47..eebf1627cea 100644 --- a/jdk/make/docs/Makefile +++ b/jdk/make/docs/Makefile @@ -84,6 +84,11 @@ ALL_SOURCE_DIRS = $(SHARE_SRC)/classes \ $(SHARE_SRC)/../solaris/classes \ $(SHARE_SRC)/../windows/classes \ $(SHARE_SRC)/doc/stub + +# List of directories that actually exist +ALL_EXISTING_SOURCE_DIRS := $(wildcard $(ALL_SOURCE_DIRS)) + +# List with classpath separator between them EMPTY:= SPACE:= $(EMPTY) $(EMPTY) RELEASEDOCS_SOURCEPATH = \ @@ -240,7 +245,8 @@ include NON_CORE_PKGS.gmk # Default target is same as docs target, create core api and all others it can # -all docs: coredocs otherdocs +all: docs +docs: coredocs otherdocs ################################################################# # Production Targets -- USE THESE TARGETS WHEN: @@ -1178,9 +1184,9 @@ $(TRACING_PACKAGES_FILE): $(DIRECTORY_CACHE) $(call PackageDependencies,$(TRACIN # # Get a cache of all the directories -$(DIRECTORY_CACHE): $(ALL_SOURCE_DIRS) +$(DIRECTORY_CACHE): $(ALL_EXISTING_SOURCE_DIRS) $(prep-target) - @for cp in $(ALL_SOURCE_DIRS) ; do \ + @for cp in $(ALL_EXISTING_SOURCE_DIRS) ; do \ $(ECHO) "$(FIND) $${cp} -type f >> $@"; \ $(FIND) $${cp} -type f >> $@; \ done From f82d12c1b4cf3f25548a6856bf33c34c9f72e47a Mon Sep 17 00:00:00 2001 From: Kelly O'Hair Date: Tue, 3 Aug 2010 10:53:21 -0700 Subject: [PATCH 46/56] 6974239: Correct reference to jdk document site in javadoc Reviewed-by: skannan --- jdk/make/docs/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/jdk/make/docs/Makefile b/jdk/make/docs/Makefile index eebf1627cea..a2aaccb130f 100644 --- a/jdk/make/docs/Makefile +++ b/jdk/make/docs/Makefile @@ -47,9 +47,9 @@ BUG_SUBMIT_LINE = Submit a bug or feature # Url to devdocs page # Was: http://java.sun.com/javase/6/webnotes/devdocs-vs-specs.html -DEV_DOCS_URL-5 = http://java.sun.com/j2se/1.5.0/docs -DEV_DOCS_URL-6 = http://download.oracle.com/docs/cd/E17409_01/javase/6/docs -DEV_DOCS_URL-7 = http://download.oracle.com/docs/cd/E17409_01/javase/7/docs +DEV_DOCS_URL-5 = http://java.sun.com/j2se/1.5.0/docs/index.html +DEV_DOCS_URL-6 = http://download.oracle.com/javase/6/docs/index.html +DEV_DOCS_URL-7 = http://download.oracle.com/javase/7/docs/index.html DEV_DOCS_URL = $(DEV_DOCS_URL-$(JDK_MINOR_VERSION)) # Url to Java Language Spec From 72990b87b14268cc232fc029a0304d6fac70b35a Mon Sep 17 00:00:00 2001 From: Erik Trimble Date: Thu, 5 Aug 2010 02:48:45 -0700 Subject: [PATCH 47/56] Added tag hs19-b04 for changeset 9dfa2b7f8640 --- hotspot/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/.hgtags b/hotspot/.hgtags index 4c1846c7f6d..5b3b994b647 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -108,3 +108,4 @@ ad1977f08c4d69162a0775fe3f9576b9fd521d10 jdk7-b100 ad1977f08c4d69162a0775fe3f9576b9fd521d10 hs19-b03 c5cadf1a07717955cf60dbaec16e35b529fd2cb0 jdk7-b102 cb4250ef73b21de6c487ea14e2b0b99eed67b4b6 jdk7-b103 +e55900b5c1b865cac17e18abc639c7dc50de7fd8 hs19-b04 From 57069c5967c0b673d2b67deecb58b9b371cb992d Mon Sep 17 00:00:00 2001 From: Christine Lu Date: Fri, 6 Aug 2010 12:51:48 -0700 Subject: [PATCH 48/56] Added tag jdk7-b104 for changeset c27b7b809bd2 --- .hgtags-top-repo | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags-top-repo b/.hgtags-top-repo index 8b24549198a..9bf4e58dcf0 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -78,3 +78,4 @@ b218a53ec7d3d42be61d31d6917a6c5c037b6f56 jdk7-b100 4193eaf5f1b82794c6a0fb1a8d11af43d1b1d611 jdk7-b101 a136a51f5113da4dad3853b74a8536ab583ab112 jdk7-b102 be2aedc4e3b1751c1310f334242ba69e90867f38 jdk7-b103 +f8be576feefce0c6695f188ef97ec16b73ad9cfd jdk7-b104 From 8ab0372f6087f65c48ebf315be971bf0c2027f9e Mon Sep 17 00:00:00 2001 From: Christine Lu Date: Fri, 6 Aug 2010 12:51:49 -0700 Subject: [PATCH 49/56] Added tag jdk7-b104 for changeset cd7adc8eaafb --- corba/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/corba/.hgtags b/corba/.hgtags index 4bf02cd1192..ffebb61ccdc 100644 --- a/corba/.hgtags +++ b/corba/.hgtags @@ -78,3 +78,4 @@ a56d734a1e970e1a21a8f4feb13053e9a33674c7 jdk7-b100 86a239832646a74811695428984b6947c0bd6dc8 jdk7-b101 78561a95779090b5106c8d0f1a75360a027ef087 jdk7-b102 11e7678c3eb169b77d9a9892fe5e3dfa1d1a0d51 jdk7-b103 +9607213481d400ac477183191cc080e1bef6f475 jdk7-b104 From b8117e7869145e7b854d3e5bfaf3cc93fb0890a9 Mon Sep 17 00:00:00 2001 From: Christine Lu Date: Fri, 6 Aug 2010 12:51:54 -0700 Subject: [PATCH 50/56] Added tag jdk7-b104 for changeset 83e5347f5988 --- hotspot/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/.hgtags b/hotspot/.hgtags index 5b3b994b647..e28f5ca8355 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -109,3 +109,4 @@ ad1977f08c4d69162a0775fe3f9576b9fd521d10 hs19-b03 c5cadf1a07717955cf60dbaec16e35b529fd2cb0 jdk7-b102 cb4250ef73b21de6c487ea14e2b0b99eed67b4b6 jdk7-b103 e55900b5c1b865cac17e18abc639c7dc50de7fd8 hs19-b04 +b4acf10eb134fe930802c97e36db65e7ccb544b5 jdk7-b104 From ba330f23de12e75d2cdac68d46b29c153b627989 Mon Sep 17 00:00:00 2001 From: Christine Lu Date: Fri, 6 Aug 2010 12:51:59 -0700 Subject: [PATCH 51/56] Added tag jdk7-b104 for changeset e4e7ae0ec293 --- jaxp/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jaxp/.hgtags b/jaxp/.hgtags index f8021c1f405..6761d4606bf 100644 --- a/jaxp/.hgtags +++ b/jaxp/.hgtags @@ -78,3 +78,4 @@ d524be5ef62e8b8cb890c59a5d2c19ef0ab50d45 jdk7-b100 17f62a566a2020fd908e77106ed885e0c4e7c14d jdk7-b101 15573625af97d01c4e24549041cba7584da7fe88 jdk7-b102 b7722e8788644507c10bb69a137de422d0300b24 jdk7-b103 +d42c4acb6424a094bdafe2ad9c8c1c7ca7fb7b7e jdk7-b104 From 6cb5b0ee66c13710ca207f706f61ad5e8ab932e3 Mon Sep 17 00:00:00 2001 From: Christine Lu Date: Fri, 6 Aug 2010 12:52:00 -0700 Subject: [PATCH 52/56] Added tag jdk7-b104 for changeset 930517ba4d97 --- jaxws/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jaxws/.hgtags b/jaxws/.hgtags index c0011497e64..f7d296f1195 100644 --- a/jaxws/.hgtags +++ b/jaxws/.hgtags @@ -78,3 +78,4 @@ bd26d0ce0c3cb43e58a8e2770cc03f26d96ffe5c jdk7-b100 b55ce274490082712f5e002b38d2eed505ca863d jdk7-b101 d8580443d1815d68e0035a0560634e50fa899288 jdk7-b102 267386d6b923f724309cab855a555e2d86a15c8f jdk7-b103 +bbc4cce6c20aeca4862804a6e8315a2350d43633 jdk7-b104 From 2791b0619d57b3369ce3c245832d8b6d35f9f55a Mon Sep 17 00:00:00 2001 From: Christine Lu Date: Fri, 6 Aug 2010 12:52:07 -0700 Subject: [PATCH 53/56] Added tag jdk7-b104 for changeset 0feaed799206 --- jdk/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jdk/.hgtags b/jdk/.hgtags index b21fc77da96..8e2227fdb7a 100644 --- a/jdk/.hgtags +++ b/jdk/.hgtags @@ -78,3 +78,4 @@ b1903d7528d33b521df42bc9291bdcdd2f444a29 jdk7-b97 d58354a69011f3d3354765fa3167567c4c4a9612 jdk7-b101 13029a61b16bec06535d4f0aa98229b358684128 jdk7-b102 6488b70a23cc6dc4b7e00809bc503c2884bafb28 jdk7-b103 +1a92820132a0221c5bdedd42d0888c57ce4cbb34 jdk7-b104 From 80a48b15c73e253b7ea546d80f53d9493913a082 Mon Sep 17 00:00:00 2001 From: Christine Lu Date: Fri, 6 Aug 2010 12:52:19 -0700 Subject: [PATCH 54/56] Added tag jdk7-b104 for changeset fef4187d7622 --- langtools/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/langtools/.hgtags b/langtools/.hgtags index b98711d8c25..5b7ec2bfa62 100644 --- a/langtools/.hgtags +++ b/langtools/.hgtags @@ -78,3 +78,4 @@ d1d7595fa824925651f09b8ffcb86c9cf39807be jdk7-b100 20a8fe72ee7b673f59c319a5222fe0eebbd92082 jdk7-b101 ff9c0a0bf7edf637a7dac5062b920924536ed79c jdk7-b102 bd85271c580ce4600b1b2d5598daa19d02174cf7 jdk7-b103 +fc7219517ec16b28d729d259020a25b05ffdf0b6 jdk7-b104 From 183ac93d8533fb326d14ba19ece8fb778246bb35 Mon Sep 17 00:00:00 2001 From: "J. Duke" Date: Wed, 5 Jul 2017 17:18:35 +0200 Subject: [PATCH 55/56] Added tag jdk7-b103 for changeset 647709708658 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 38cd5dae51c..ca9bc99858e 100644 --- a/.hgtags +++ b/.hgtags @@ -77,3 +77,4 @@ c4c8a5bc54f66abc68cd185d9294042121922154 jdk7-b99 2d6ba7a221915bdf0311acc5641c7f3875cb793e jdk7-b100 2548ac036b8fca3326d058d758e6df8355a42469 jdk7-b101 88db80c8e49cea352c2900f689600dc410761c1f jdk7-b102 +64770970865839b0443066370e7d476ef47e90cd jdk7-b103 From c88a15e039863c1334edb5750e3cd6c0fcf52162 Mon Sep 17 00:00:00 2001 From: "J. Duke" Date: Wed, 5 Jul 2017 17:19:01 +0200 Subject: [PATCH 56/56] Added tag jdk7-b104 for changeset 10bc903a228d --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index ca9bc99858e..a9f3d0f406a 100644 --- a/.hgtags +++ b/.hgtags @@ -78,3 +78,4 @@ c4c8a5bc54f66abc68cd185d9294042121922154 jdk7-b99 2548ac036b8fca3326d058d758e6df8355a42469 jdk7-b101 88db80c8e49cea352c2900f689600dc410761c1f jdk7-b102 64770970865839b0443066370e7d476ef47e90cd jdk7-b103 +10bc903a228d3a8efdf46fb8c3fcf82a59b88bc5 jdk7-b104