From 968deb7658481da8c001e4ec94802dab8292cbf4 Mon Sep 17 00:00:00 2001 From: Antonios Printezis Date: Mon, 28 Jun 2010 14:13:18 -0400 Subject: [PATCH 001/110] 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 002/110] 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 003/110] 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 004/110] 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 005/110] 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 ec05f75ccd971c2b8e83e974b1c4abb629498092 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Tue, 13 Jul 2010 19:14:09 -0700 Subject: [PATCH 006/110] 6966732: replace use of static Log.getLocalizedString with non-static alternative where possible Reviewed-by: darcy --- .../com/sun/tools/javac/jvm/ClassReader.java | 4 +-- .../com/sun/tools/javac/jvm/ClassWriter.java | 2 +- .../sun/tools/javac/main/JavaCompiler.java | 12 +++---- .../JavacProcessingEnvironment.java | 35 ++++++++----------- .../classes/com/sun/tools/javac/util/Log.java | 29 +++++++++++++-- 5 files changed, 50 insertions(+), 32 deletions(-) diff --git a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java index d16dc1d2ce8..09d5d7c5b2f 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java +++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java @@ -2628,7 +2628,7 @@ public class ClassReader implements Completer { * @param arg An argument for substitution into the output string. */ private void printVerbose(String key, CharSequence arg) { - Log.printLines(log.noticeWriter, Log.getLocalizedString("verbose." + key, arg)); + log.printNoteLines("verbose." + key, arg); } /** Output for "-checkclassfile" option. @@ -2636,7 +2636,7 @@ public class ClassReader implements Completer { * @param arg An argument for substitution into the output string. */ private void printCCF(String key, Object arg) { - Log.printLines(log.noticeWriter, Log.getLocalizedString(key, arg)); + log.printNoteLines(key, arg); } diff --git a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java index 687d5344323..e0af0d914f9 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java +++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java @@ -1604,7 +1604,7 @@ public class ClassWriter extends ClassFile { try { writeClassFile(out, c); if (verbose) - log.errWriter.println(Log.getLocalizedString("verbose.wrote.file", outFile)); + log.printErrLines("verbose.wrote.file", outFile); out.close(); out = null; } finally { diff --git a/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java b/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java index d65aca9cdb8..86ce0da81cd 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java +++ b/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java @@ -1105,7 +1105,7 @@ public class JavaCompiler implements ClassReader.SourceCompleter { return env; if (verboseCompilePolicy) - Log.printLines(log.noticeWriter, "[attribute " + env.enclClass.sym + "]"); + printNote("[attribute " + env.enclClass.sym + "]"); if (verbose) printVerbose("checking.attribution", env.enclClass.sym); @@ -1527,19 +1527,19 @@ public class JavaCompiler implements ClassReader.SourceCompleter { * @param arg An argument for substitution into the output string. */ protected void printVerbose(String key, Object arg) { - Log.printLines(log.noticeWriter, Log.getLocalizedString("verbose." + key, arg)); + log.printNoteLines("verbose." + key, arg); } /** Print numbers of errors and warnings. */ protected void printCount(String kind, int count) { if (count != 0) { - String text; + String key; if (count == 1) - text = Log.getLocalizedString("count." + kind, String.valueOf(count)); + key = "count." + kind; else - text = Log.getLocalizedString("count." + kind + ".plural", String.valueOf(count)); - Log.printLines(log.errWriter, text); + key = "count." + kind + ".plural"; + log.printErrLines(key, String.valueOf(count)); log.errWriter.flush(); } } diff --git a/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java b/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java index 2f605fdc528..800a1a21e1b 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java +++ b/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java @@ -654,9 +654,6 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea Set annotationsPresent, List topLevelClasses, List packageInfoFiles) { - // Writer for -XprintRounds and -XprintProcessorInfo data - PrintWriter xout = context.get(Log.outKey); - Map unmatchedAnnotations = new HashMap(annotationsPresent.size()); @@ -708,10 +705,10 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea ps.removeSupportedOptions(unmatchedProcessorOptions); if (printProcessorInfo || verbose) { - xout.println(Log.getLocalizedString("x.print.processor.info", - ps.processor.getClass().getName(), - matchedNames.toString(), - processingResult)); + log.printNoteLines("x.print.processor.info", + ps.processor.getClass().getName(), + matchedNames.toString(), + processingResult); } if (processingResult) { @@ -795,8 +792,6 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea throws IOException { log = Log.instance(context); - // Writer for -XprintRounds and -XprintProcessorInfo data - PrintWriter xout = context.get(Log.outKey); TaskListener taskListener = context.get(TaskListener.class); JavaCompiler compiler = JavaCompiler.instance(context); @@ -839,7 +834,7 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea this.context = currentContext; roundNumber++; - printRoundInfo(xout, roundNumber, topLevelClasses, annotationsPresent, false); + printRoundInfo(roundNumber, topLevelClasses, annotationsPresent, false); if (taskListener != null) taskListener.started(new TaskEvent(TaskEvent.Kind.ANNOTATION_PROCESSING_ROUND)); @@ -908,7 +903,7 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea break runAround; // No new files } } - roots = runLastRound(xout, roundNumber, errorStatus, compiler, roots, taskListener); + roots = runLastRound(roundNumber, errorStatus, compiler, roots, taskListener); // Set error status for any files compiled and generated in // the last round if (log.unrecoverableError) @@ -982,8 +977,7 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea } // Call the last round of annotation processing - private List runLastRound(PrintWriter xout, - int roundNumber, + private List runLastRound(int roundNumber, boolean errorStatus, JavaCompiler compiler, List roots, @@ -991,7 +985,7 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea roundNumber++; List noTopLevelClasses = List.nil(); Set noAnnotations = Collections.emptySet(); - printRoundInfo(xout, roundNumber, noTopLevelClasses, noAnnotations, true); + printRoundInfo(roundNumber, noTopLevelClasses, noAnnotations, true); Set emptyRootElements = Collections.emptySet(); // immutable RoundEnvironment renv = new JavacRoundEnvironment(true, @@ -1032,17 +1026,16 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea } } - private void printRoundInfo(PrintWriter xout, - int roundNumber, + private void printRoundInfo(int roundNumber, List topLevelClasses, Set annotationsPresent, boolean lastRound) { if (printRounds || verbose) { - xout.println(Log.getLocalizedString("x.print.rounds", - roundNumber, - "{" + topLevelClasses.toString(", ") + "}", - annotationsPresent, - lastRound)); + log.printNoteLines("x.print.rounds", + roundNumber, + "{" + topLevelClasses.toString(", ") + "}", + annotationsPresent, + lastRound); } } diff --git a/langtools/src/share/classes/com/sun/tools/javac/util/Log.java b/langtools/src/share/classes/com/sun/tools/javac/util/Log.java index 6fcc4b0fbcb..66d5e947ab2 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/util/Log.java +++ b/langtools/src/share/classes/com/sun/tools/javac/util/Log.java @@ -269,7 +269,7 @@ public class Log extends AbstractLog { */ public void prompt() { if (promptOnError) { - System.err.println(getLocalizedString("resume.abort")); + System.err.println(localize("resume.abort")); char ch; try { while (true) { @@ -317,8 +317,23 @@ public class Log extends AbstractLog { if (msg.length() != 0) writer.println(msg); } + /** Print the text of a message to the errWriter stream, + * translating newlines appropriately for the platform. + */ + public void printErrLines(String key, Object... args) { + printLines(errWriter, localize(key, args)); + } + + + /** Print the text of a message to the noticeWriter stream, + * translating newlines appropriately for the platform. + */ + public void printNoteLines(String key, Object... args) { + printLines(noticeWriter, localize(key, args)); + } + protected void directError(String key, Object... args) { - printLines(errWriter, getLocalizedString(key, args)); + printErrLines(key, args); errWriter.flush(); } @@ -426,6 +441,8 @@ public class Log extends AbstractLog { } /** Find a localized string in the resource bundle. + * Because this method is static, it ignores the locale. + * Use localize(key, args) when possible. * @param key The key for the localized string. * @param args Fields to substitute into the string. */ @@ -433,6 +450,14 @@ public class Log extends AbstractLog { return JavacMessages.getDefaultLocalizedString("compiler.misc." + key, args); } + /** Find a localized string in the resource bundle. + * @param key The key for the localized string. + * @param args Fields to substitute into the string. + */ + public String localize(String key, Object... args) { + return messages.getLocalizedString("compiler.misc." + key, args); + } + /*************************************************************************** * raw error messages without internationalization; used for experimentation * and quick prototyping From 5db54afdeaad361d29feca7f7b66a050cb26d565 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Tue, 13 Jul 2010 19:17:55 -0700 Subject: [PATCH 007/110] 6968434: test CheckResourceKeys fails on control builds Reviewed-by: darcy --- .../tools/javac/diags/CheckResourceKeys.java | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/langtools/test/tools/javac/diags/CheckResourceKeys.java b/langtools/test/tools/javac/diags/CheckResourceKeys.java index 7b60ae68af4..32ef8ed4a4a 100644 --- a/langtools/test/tools/javac/diags/CheckResourceKeys.java +++ b/langtools/test/tools/javac/diags/CheckResourceKeys.java @@ -294,6 +294,7 @@ public class CheckResourceKeys { Set results = new TreeSet(); JavaCompiler c = ToolProvider.getSystemJavaCompiler(); JavaFileManager fm = c.getStandardFileManager(null, null, null); + JavaFileManager.Location javacLoc = findJavacLocation(fm); String[] pkgs = { "javax.annotation.processing", "javax.lang.model", @@ -302,7 +303,7 @@ public class CheckResourceKeys { "com.sun.tools.javac" }; for (String pkg: pkgs) { - for (JavaFileObject fo: fm.list(StandardLocation.PLATFORM_CLASS_PATH, + for (JavaFileObject fo: fm.list(javacLoc, pkg, EnumSet.of(JavaFileObject.Kind.CLASS), true)) { String name = fo.getName(); // ignore resource files, and files which are not really part of javac @@ -316,6 +317,23 @@ public class CheckResourceKeys { return results; } + // depending on how the test is run, javac may be on bootclasspath or classpath + JavaFileManager.Location findJavacLocation(JavaFileManager fm) { + JavaFileManager.Location[] locns = + { StandardLocation.PLATFORM_CLASS_PATH, StandardLocation.CLASS_PATH }; + try { + for (JavaFileManager.Location l: locns) { + JavaFileObject fo = fm.getJavaFileForInput(l, + "com.sun.tools.javac.Main", JavaFileObject.Kind.CLASS); + if (fo != null) + return l; + } + } catch (IOException e) { + throw new Error(e); + } + throw new IllegalStateException("Cannot find javac"); + } + /** * Get the set of strings from a class file. * Only strings that look like they might be a resource key are returned. From a1e7efde4abf16e5e06a3e1384c663146eb35398 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Tue, 13 Jul 2010 19:20:48 -0700 Subject: [PATCH 008/110] 6968789: incorrect text in "diamond not supported" message Reviewed-by: darcy --- .../classes/com/sun/tools/javac/resources/compiler.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties index dec8126dd43..8fee222ad64 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties +++ b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties @@ -1263,7 +1263,7 @@ compiler.err.enums.not.supported.in.source=\ compiler.err.diamond.not.supported.in.source=\ diamond operator is not supported in -source {0}\n\ -(use -source 7 or higher to enable multi-catch statement) +(use -source 7 or higher to enable diamond operator) compiler.err.multicatch.not.supported.in.source=\ multi-catch statement is not supported in -source {0}\n\ From aa93fd77012f7d1f02c33690683f59bc3679b898 Mon Sep 17 00:00:00 2001 From: Mahmood Ali Date: Thu, 15 Jul 2010 16:31:02 +0100 Subject: [PATCH 009/110] 6967002: JDK7 b99 javac compilation error (java.lang.AssertionError) Bug in JavacParser related to parsing of type annotations in varargs position Reviewed-by: jjg --- .../sun/tools/javac/parser/JavacParser.java | 8 +++-- .../typeAnnotations/6967002/T6967002.java | 35 +++++++++++++++++++ .../typeAnnotations/6967002/T6967002.out | 8 +++++ 3 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 langtools/test/tools/javac/typeAnnotations/6967002/T6967002.java create mode 100644 langtools/test/tools/javac/typeAnnotations/6967002/T6967002.out diff --git a/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java b/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java index 01ab573d00e..32ae4d52a19 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java +++ b/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java @@ -1151,8 +1151,12 @@ public class JavacParser implements Parser { t = toP(F.at(pos).Select(t, ident())); break; case ELLIPSIS: - assert this.permitTypeAnnotationsPushBack; - typeAnnotationsPushedBack = annos; + if (this.permitTypeAnnotationsPushBack) { + this.typeAnnotationsPushedBack = annos; + } else if (annos.nonEmpty()) { + // Don't return here -- error recovery attempt + illegal(annos.head.pos); + } break loop; default: break loop; diff --git a/langtools/test/tools/javac/typeAnnotations/6967002/T6967002.java b/langtools/test/tools/javac/typeAnnotations/6967002/T6967002.java new file mode 100644 index 00000000000..317cf34199e --- /dev/null +++ b/langtools/test/tools/javac/typeAnnotations/6967002/T6967002.java @@ -0,0 +1,35 @@ +/* + * 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 6967002 + * @summary JDK7 b99 javac compilation error (java.lang.AssertionError) + * @author Maurizio Cimadamore + * @compile/fail/ref=T6967002.out -XDrawDiagnostics T6967002.java + */ +class Test { + private static void m(byte[] octets) { + return m(octets..., ?); + } +} diff --git a/langtools/test/tools/javac/typeAnnotations/6967002/T6967002.out b/langtools/test/tools/javac/typeAnnotations/6967002/T6967002.out new file mode 100644 index 00000000000..18b75307f04 --- /dev/null +++ b/langtools/test/tools/javac/typeAnnotations/6967002/T6967002.out @@ -0,0 +1,8 @@ +T6967002.java:33:22: compiler.err.expected: ')' +T6967002.java:33:25: compiler.err.illegal.start.of.expr +T6967002.java:33:28: compiler.err.illegal.start.of.expr +T6967002.java:33:29: compiler.err.illegal.start.of.expr +T6967002.java:33:27: compiler.err.not.stmt +T6967002.java:33:30: compiler.err.expected: ';' +T6967002.java:35:2: compiler.err.premature.eof +7 errors From 9c273720d69c69bb1fff7b0247a64cfee0742048 Mon Sep 17 00:00:00 2001 From: Tomas Zezula Date: Thu, 15 Jul 2010 16:31:56 +0100 Subject: [PATCH 010/110] 6964669: javac reports error on miranda methods Synthetic name clash check should not apply to miranda methods Reviewed-by: jjg --- .../com/sun/tools/javac/comp/Check.java | 1 + .../tools/javac/miranda/6964669/T6964669.java | 29 +++++++++++++++++++ .../tools/javac/miranda/6964669/pkg/A.java | 26 +++++++++++++++++ .../tools/javac/miranda/6964669/pkg/B.java | 28 ++++++++++++++++++ .../tools/javac/miranda/6964669/pkg/C.java | 28 ++++++++++++++++++ 5 files changed, 112 insertions(+) create mode 100644 langtools/test/tools/javac/miranda/6964669/T6964669.java create mode 100644 langtools/test/tools/javac/miranda/6964669/pkg/A.java create mode 100644 langtools/test/tools/javac/miranda/6964669/pkg/B.java create mode 100644 langtools/test/tools/javac/miranda/6964669/pkg/C.java diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java index 09bf0bf0865..3b9999c1794 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java @@ -1853,6 +1853,7 @@ public class Check { types.isSameType(types.erasure(sym.type), types.erasure(e.sym.type)) && sym != e.sym && (sym.flags() & Flags.SYNTHETIC) != (e.sym.flags() & Flags.SYNTHETIC) && + (sym.flags() & IPROXY) == 0 && (e.sym.flags() & IPROXY) == 0 && (sym.flags() & BRIDGE) == 0 && (e.sym.flags() & BRIDGE) == 0) { syntheticError(pos, (e.sym.flags() & SYNTHETIC) == 0 ? e.sym : sym); return; diff --git a/langtools/test/tools/javac/miranda/6964669/T6964669.java b/langtools/test/tools/javac/miranda/6964669/T6964669.java new file mode 100644 index 00000000000..6023b179338 --- /dev/null +++ b/langtools/test/tools/javac/miranda/6964669/T6964669.java @@ -0,0 +1,29 @@ +/* + * 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 6964669 + * @summary javac reports error on miranda methods + * @compile -source 1.2 -target 1.1 pkg/A.java pkg/B.java pkg/C.java + */ diff --git a/langtools/test/tools/javac/miranda/6964669/pkg/A.java b/langtools/test/tools/javac/miranda/6964669/pkg/A.java new file mode 100644 index 00000000000..71ee85449f7 --- /dev/null +++ b/langtools/test/tools/javac/miranda/6964669/pkg/A.java @@ -0,0 +1,26 @@ +/* + * 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. + */ + +package pkg; + +public abstract class A implements C {} diff --git a/langtools/test/tools/javac/miranda/6964669/pkg/B.java b/langtools/test/tools/javac/miranda/6964669/pkg/B.java new file mode 100644 index 00000000000..efafcfe1364 --- /dev/null +++ b/langtools/test/tools/javac/miranda/6964669/pkg/B.java @@ -0,0 +1,28 @@ +/* + * 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. + */ + +package pkg; + +public class B extends A { + public void a() {} +} diff --git a/langtools/test/tools/javac/miranda/6964669/pkg/C.java b/langtools/test/tools/javac/miranda/6964669/pkg/C.java new file mode 100644 index 00000000000..9508349c0fd --- /dev/null +++ b/langtools/test/tools/javac/miranda/6964669/pkg/C.java @@ -0,0 +1,28 @@ +/* + * 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. + */ + +package pkg; + +public interface C { + public void a(); +} From 7dcb52915b45ad916c7631fa71368613dfaa6224 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Thu, 15 Jul 2010 18:02:05 -0700 Subject: [PATCH 011/110] 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 012/110] 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 640336ebe64e38a15ba89081203921c5a5b20499 Mon Sep 17 00:00:00 2001 From: Alan Bateman Date: Fri, 16 Jul 2010 13:14:03 +0100 Subject: [PATCH 013/110] 6649594: Intermittent IOExceptions during dynamic attach on linux and solaris Reviewed-by: dcubed, dholmes --- .../src/os/linux/vm/attachListener_linux.cpp | 71 ++++++++++--------- .../os/solaris/vm/attachListener_solaris.cpp | 31 +++++--- 2 files changed, 58 insertions(+), 44 deletions(-) diff --git a/hotspot/src/os/linux/vm/attachListener_linux.cpp b/hotspot/src/os/linux/vm/attachListener_linux.cpp index 222ffa5acb2..837410ab3bd 100644 --- a/hotspot/src/os/linux/vm/attachListener_linux.cpp +++ b/hotspot/src/os/linux/vm/attachListener_linux.cpp @@ -32,11 +32,15 @@ #include #include +#ifndef UNIX_PATH_MAX +#define UNIX_PATH_MAX sizeof(((struct sockaddr_un *)0)->sun_path) +#endif + // The attach mechanism on Linux uses a UNIX domain socket. An attach listener // thread is created at startup or is created on-demand via a signal from // the client tool. The attach listener creates a socket and binds it to a file // in the filesystem. The attach listener then acts as a simple (single- -// threaded) server - tt waits for a client to connect, reads the request, +// threaded) server - it waits for a client to connect, reads the request, // executes it, and returns the response to the client via the socket // connection. // @@ -54,7 +58,7 @@ class LinuxAttachOperation; class LinuxAttachListener: AllStatic { private: // the path to which we bind the UNIX domain socket - static char _path[PATH_MAX+1]; + static char _path[UNIX_PATH_MAX]; static bool _has_path; // the file descriptor for the listening socket @@ -64,8 +68,8 @@ class LinuxAttachListener: AllStatic { if (path == NULL) { _has_path = false; } else { - strncpy(_path, path, PATH_MAX); - _path[PATH_MAX] = '\0'; + strncpy(_path, path, UNIX_PATH_MAX); + _path[UNIX_PATH_MAX-1] = '\0'; _has_path = true; } } @@ -113,7 +117,7 @@ class LinuxAttachOperation: public AttachOperation { }; // statics -char LinuxAttachListener::_path[PATH_MAX+1]; +char LinuxAttachListener::_path[UNIX_PATH_MAX]; bool LinuxAttachListener::_has_path; int LinuxAttachListener::_listener = -1; @@ -163,54 +167,53 @@ extern "C" { // Initialization - create a listener socket and bind it to a file int LinuxAttachListener::init() { - char path[PATH_MAX+1]; // socket file - int listener; // listener socket (file descriptor) + char path[UNIX_PATH_MAX]; // socket file + char initial_path[UNIX_PATH_MAX]; // socket file during setup + int listener; // listener socket (file descriptor) // register function to cleanup ::atexit(listener_cleanup); + int n = snprintf(path, UNIX_PATH_MAX, "%s/.java_pid%d", + os::get_temp_directory(), os::current_process_id()); + if (n <= (int)UNIX_PATH_MAX) { + n = snprintf(initial_path, UNIX_PATH_MAX, "%s.tmp", path); + } + if (n > (int)UNIX_PATH_MAX) { + return -1; + } + // create the listener socket listener = ::socket(PF_UNIX, SOCK_STREAM, 0); if (listener == -1) { return -1; } - int res = -1; + // bind socket struct sockaddr_un addr; addr.sun_family = AF_UNIX; - - // FIXME: Prior to b39 the tool-side API expected to find the well - // known file in the working directory. To allow this libjvm.so work with - // a pre-b39 SDK we create it in the working directory if - // +StartAttachListener is used is used. All unit tests for this feature - // currently used this flag. Once b39 SDK has been promoted we can remove - // this code. - if (StartAttachListener) { - sprintf(path, ".java_pid%d", os::current_process_id()); - strcpy(addr.sun_path, path); - ::unlink(path); - res = ::bind(listener, (struct sockaddr*)&addr, sizeof(addr)); - } + strcpy(addr.sun_path, initial_path); + ::unlink(initial_path); + int res = ::bind(listener, (struct sockaddr*)&addr, sizeof(addr)); if (res == -1) { - snprintf(path, PATH_MAX+1, "%s/.java_pid%d", - os::get_temp_directory(), os::current_process_id()); - strcpy(addr.sun_path, path); - ::unlink(path); - res = ::bind(listener, (struct sockaddr*)&addr, sizeof(addr)); + RESTARTABLE(::close(listener), res); + return -1; + } + + // put in listen mode, set permissions, and rename into place + res = ::listen(listener, 5); + if (res == 0) { + RESTARTABLE(::chmod(initial_path, S_IREAD|S_IWRITE), res); + if (res == 0) { + res = ::rename(initial_path, path); + } } if (res == -1) { RESTARTABLE(::close(listener), res); + ::unlink(initial_path); return -1; } set_path(path); - - // put in listen mode and set permission - if ((::listen(listener, 5) == -1) || (::chmod(path, S_IREAD|S_IWRITE) == -1)) { - RESTARTABLE(::close(listener), res); - ::unlink(path); - set_path(NULL); - return -1; - } set_listener(listener); return 0; diff --git a/hotspot/src/os/solaris/vm/attachListener_solaris.cpp b/hotspot/src/os/solaris/vm/attachListener_solaris.cpp index a88f8861fbd..9ae81cb53d5 100644 --- a/hotspot/src/os/solaris/vm/attachListener_solaris.cpp +++ b/hotspot/src/os/solaris/vm/attachListener_solaris.cpp @@ -364,6 +364,7 @@ extern "C" { // Create the door int SolarisAttachListener::create_door() { char door_path[PATH_MAX+1]; + char initial_path[PATH_MAX+1]; int fd, res; // register exit function @@ -375,36 +376,46 @@ int SolarisAttachListener::create_door() { return -1; } + // create initial file to attach door descriptor snprintf(door_path, sizeof(door_path), "%s/.java_pid%d", os::get_temp_directory(), os::current_process_id()); - RESTARTABLE(::creat(door_path, S_IRUSR | S_IWUSR), fd); - + snprintf(initial_path, sizeof(initial_path), "%s.tmp", door_path); + RESTARTABLE(::creat(initial_path, S_IRUSR | S_IWUSR), fd); if (fd == -1) { - debug_only(warning("attempt to create %s failed", door_path)); + debug_only(warning("attempt to create %s failed", initial_path)); + ::door_revoke(dd); return -1; } assert(fd >= 0, "bad file descriptor"); - set_door_path(door_path); RESTARTABLE(::close(fd), res); // attach the door descriptor to the file - if ((res = ::fattach(dd, door_path)) == -1) { + if ((res = ::fattach(dd, initial_path)) == -1) { // if busy then detach and try again if (errno == EBUSY) { - ::fdetach(door_path); - res = ::fattach(dd, door_path); + ::fdetach(initial_path); + res = ::fattach(dd, initial_path); } if (res == -1) { ::door_revoke(dd); dd = -1; } } + + // rename file so that clients can attach + if (dd >= 0) { + if (::rename(initial_path, door_path) == -1) { + RESTARTABLE(::close(dd), res); + ::fdetach(initial_path); + dd = -1; + } + } if (dd >= 0) { set_door_descriptor(dd); + set_door_path(door_path); } else { - // unable to create door or attach it to the file - ::unlink(door_path); - set_door_path(NULL); + // unable to create door, attach it to file, or rename file into place + ::unlink(initial_path); return -1; } From 98f8ed01aadc094d41f7f9d52946f8d4526e63f3 Mon Sep 17 00:00:00 2001 From: Xueming Shen Date: Fri, 16 Jul 2010 16:45:52 -0400 Subject: [PATCH 014/110] 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 015/110] 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 985efdc4759d06cdf422f9e6b2f26148640b8fa8 Mon Sep 17 00:00:00 2001 From: Tom Ball Date: Fri, 16 Jul 2010 19:35:24 -0700 Subject: [PATCH 016/110] 6911256: Project Coin: Support Automatic Resource Management (ARM) blocks in the compiler 6964740: Project Coin: More tests for ARM compiler changes 6965277: Project Coin: Correctness issues in ARM implementation 6967065: add -Xlint warning category for Automatic Resource Management (ARM) Reviewed-by: jjb, darcy, mcimadamore, jjg, briangoetz --- langtools/make/build.properties | 3 +- .../classes/com/sun/source/tree/TryTree.java | 1 + .../com/sun/source/util/TreeScanner.java | 3 +- .../com/sun/tools/javac/code/Lint.java | 7 +- .../com/sun/tools/javac/code/Source.java | 3 + .../com/sun/tools/javac/code/Symbol.java | 9 +- .../com/sun/tools/javac/code/Symtab.java | 10 + .../com/sun/tools/javac/comp/Attr.java | 60 +- .../com/sun/tools/javac/comp/Check.java | 6 +- .../com/sun/tools/javac/comp/Flow.java | 52 +- .../com/sun/tools/javac/comp/Lower.java | 148 ++++ .../com/sun/tools/javac/comp/TransTypes.java | 8 + .../com/sun/tools/javac/jvm/CRTable.java | 1 + .../sun/tools/javac/parser/JavacParser.java | 62 +- .../tools/javac/resources/compiler.properties | 14 + .../com/sun/tools/javac/tree/JCTree.java | 15 +- .../com/sun/tools/javac/tree/Pretty.java | 13 + .../com/sun/tools/javac/tree/TreeCopier.java | 3 +- .../com/sun/tools/javac/tree/TreeMaker.java | 9 +- .../com/sun/tools/javac/tree/TreeScanner.java | 1 + .../sun/tools/javac/tree/TreeTranslator.java | 1 + .../com/sun/tools/javac/util/Names.java | 5 + .../tools/javac/TryWithResources/ArmLint.java | 55 ++ .../tools/javac/TryWithResources/ArmLint.out | 3 + .../tools/javac/TryWithResources/BadTwr.java | 36 + .../tools/javac/TryWithResources/BadTwr.out | 5 + .../javac/TryWithResources/BadTwrSyntax.java | 22 + .../javac/TryWithResources/BadTwrSyntax.out | 2 + .../TryWithResources/DuplicateResource.java | 65 ++ .../DuplicateResourceDecl.java | 20 + .../DuplicateResourceDecl.out | 2 + .../javac/TryWithResources/ImplicitFinal.java | 27 + .../javac/TryWithResources/ImplicitFinal.out | 2 + .../javac/TryWithResources/PlainTry.java | 15 + .../tools/javac/TryWithResources/PlainTry.out | 2 + .../javac/TryWithResources/PlainTry6.out | 2 + .../TryWithResources/ResourceOutsideTry.java | 23 + .../TryWithResources/ResourceOutsideTry.out | 3 + .../TryWithResources/ResourceTypeVar.java | 43 + .../tools/javac/TryWithResources/TwrFlow.java | 39 + .../tools/javac/TryWithResources/TwrFlow.out | 5 + .../javac/TryWithResources/TwrInference.java | 43 + .../TryWithResources/TwrIntersection.java | 47 ++ .../TryWithResources/TwrIntersection02.java | 37 + .../TryWithResources/TwrIntersection02.out | 3 + .../javac/TryWithResources/TwrMultiCatch.java | 81 ++ .../TryWithResources/TwrOnNonResource.java | 42 + .../TryWithResources/TwrOnNonResource.out | 7 + .../javac/TryWithResources/TwrTests.java | 742 ++++++++++++++++++ .../javac/TryWithResources/WeirdTwr.java | 48 ++ .../model/element/TestResourceVariable.java | 113 +++ 51 files changed, 1950 insertions(+), 18 deletions(-) create mode 100644 langtools/test/tools/javac/TryWithResources/ArmLint.java create mode 100644 langtools/test/tools/javac/TryWithResources/ArmLint.out create mode 100644 langtools/test/tools/javac/TryWithResources/BadTwr.java create mode 100644 langtools/test/tools/javac/TryWithResources/BadTwr.out create mode 100644 langtools/test/tools/javac/TryWithResources/BadTwrSyntax.java create mode 100644 langtools/test/tools/javac/TryWithResources/BadTwrSyntax.out create mode 100644 langtools/test/tools/javac/TryWithResources/DuplicateResource.java create mode 100644 langtools/test/tools/javac/TryWithResources/DuplicateResourceDecl.java create mode 100644 langtools/test/tools/javac/TryWithResources/DuplicateResourceDecl.out create mode 100644 langtools/test/tools/javac/TryWithResources/ImplicitFinal.java create mode 100644 langtools/test/tools/javac/TryWithResources/ImplicitFinal.out create mode 100644 langtools/test/tools/javac/TryWithResources/PlainTry.java create mode 100644 langtools/test/tools/javac/TryWithResources/PlainTry.out create mode 100644 langtools/test/tools/javac/TryWithResources/PlainTry6.out create mode 100644 langtools/test/tools/javac/TryWithResources/ResourceOutsideTry.java create mode 100644 langtools/test/tools/javac/TryWithResources/ResourceOutsideTry.out create mode 100644 langtools/test/tools/javac/TryWithResources/ResourceTypeVar.java create mode 100644 langtools/test/tools/javac/TryWithResources/TwrFlow.java create mode 100644 langtools/test/tools/javac/TryWithResources/TwrFlow.out create mode 100644 langtools/test/tools/javac/TryWithResources/TwrInference.java create mode 100644 langtools/test/tools/javac/TryWithResources/TwrIntersection.java create mode 100644 langtools/test/tools/javac/TryWithResources/TwrIntersection02.java create mode 100644 langtools/test/tools/javac/TryWithResources/TwrIntersection02.out create mode 100644 langtools/test/tools/javac/TryWithResources/TwrMultiCatch.java create mode 100644 langtools/test/tools/javac/TryWithResources/TwrOnNonResource.java create mode 100644 langtools/test/tools/javac/TryWithResources/TwrOnNonResource.out create mode 100644 langtools/test/tools/javac/TryWithResources/TwrTests.java create mode 100644 langtools/test/tools/javac/TryWithResources/WeirdTwr.java create mode 100644 langtools/test/tools/javac/processing/model/element/TestResourceVariable.java diff --git a/langtools/make/build.properties b/langtools/make/build.properties index f9a87321d41..4ba6256f053 100644 --- a/langtools/make/build.properties +++ b/langtools/make/build.properties @@ -107,7 +107,8 @@ javac.includes = \ javax/annotation/processing/ \ javax/lang/model/ \ javax/tools/ \ - com/sun/source/ com/sun/tools/javac/ + com/sun/source/ \ + com/sun/tools/javac/ javac.tests = \ tools/javac diff --git a/langtools/src/share/classes/com/sun/source/tree/TryTree.java b/langtools/src/share/classes/com/sun/source/tree/TryTree.java index 8eeedb095d9..6e31bee66b0 100644 --- a/langtools/src/share/classes/com/sun/source/tree/TryTree.java +++ b/langtools/src/share/classes/com/sun/source/tree/TryTree.java @@ -49,4 +49,5 @@ public interface TryTree extends StatementTree { BlockTree getBlock(); List getCatches(); BlockTree getFinallyBlock(); + List getResources(); } diff --git a/langtools/src/share/classes/com/sun/source/util/TreeScanner.java b/langtools/src/share/classes/com/sun/source/util/TreeScanner.java index d4448fb6d25..dbb2d303809 100644 --- a/langtools/src/share/classes/com/sun/source/util/TreeScanner.java +++ b/langtools/src/share/classes/com/sun/source/util/TreeScanner.java @@ -209,7 +209,8 @@ public class TreeScanner implements TreeVisitor { } public R visitTry(TryTree node, P p) { - R r = scan(node.getBlock(), p); + R r = scan(node.getResources(), p); + r = scanAndReduce(node.getBlock(), p, r); r = scanAndReduce(node.getCatches(), p, r); r = scanAndReduce(node.getFinallyBlock(), p, r); return r; diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/Lint.java b/langtools/src/share/classes/com/sun/tools/javac/code/Lint.java index c02c5bb9e55..319865950f9 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/Lint.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Lint.java @@ -208,7 +208,12 @@ public class Lint /** * Warn about potentially unsafe vararg methods */ - VARARGS("varargs"); + VARARGS("varargs"), + + /** + * Warn about arm resources + */ + ARM("arm"); LintCategory(String option) { this(option, false); diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/Source.java b/langtools/src/share/classes/com/sun/tools/javac/code/Source.java index bce1513d22a..5dbd6f4fd16 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/Source.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Source.java @@ -159,6 +159,9 @@ public enum Source { public boolean enforceMandatoryWarnings() { return compareTo(JDK1_5) >= 0; } + public boolean allowTryWithResources() { + return compareTo(JDK1_7) >= 0; + } public boolean allowTypeAnnotations() { return compareTo(JDK1_7) >= 0; } diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java b/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java index 2c75a0cd1f9..9faa4b06f74 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java @@ -993,12 +993,17 @@ public abstract class Symbol implements Element { return data == ElementKind.EXCEPTION_PARAMETER; } + public boolean isResourceVariable() { + return data == ElementKind.RESOURCE_VARIABLE; + } + public Object getConstValue() { // TODO: Consider if getConstValue and getConstantValue can be collapsed - if (data == ElementKind.EXCEPTION_PARAMETER) { + if (data == ElementKind.EXCEPTION_PARAMETER || + data == ElementKind.RESOURCE_VARIABLE) { return null; } else if (data instanceof Callable) { - // In this case, this is final a variable, with an as + // In this case, this is a final variable, with an as // yet unevaluated initializer. Callable eval = (Callable)data; data = null; // to make sure we don't evaluate this twice. diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/Symtab.java b/langtools/src/share/classes/com/sun/tools/javac/code/Symtab.java index 947691e3522..1d037c29ba7 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/Symtab.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Symtab.java @@ -148,6 +148,7 @@ public class Symtab { public final Type inheritedType; public final Type proprietaryType; public final Type systemType; + public final Type autoCloseableType; /** The symbol representing the length field of an array. */ @@ -159,6 +160,9 @@ public class Symtab { /** The symbol representing the final finalize method on enums */ public final MethodSymbol enumFinalFinalize; + /** The symbol representing the close method on TWR AutoCloseable type */ + public final MethodSymbol autoCloseableClose; + /** The predefined type that belongs to a tag. */ public final Type[] typeOfTag = new Type[TypeTags.TypeTagCount]; @@ -444,6 +448,12 @@ public class Symtab { suppressWarningsType = enterClass("java.lang.SuppressWarnings"); inheritedType = enterClass("java.lang.annotation.Inherited"); systemType = enterClass("java.lang.System"); + autoCloseableType = enterClass("java.lang.AutoCloseable"); + autoCloseableClose = new MethodSymbol(PUBLIC, + names.close, + new MethodType(List.nil(), voidType, + List.of(exceptionType), methodClass), + autoCloseableType.tsym); synthesizeEmptyInterfaceIfMissing(cloneableType); synthesizeEmptyInterfaceIfMissing(serializableType); diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java index ca63b46b55e..1c28ba75c2f 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java @@ -192,7 +192,7 @@ public class Attr extends JCTree.Visitor { Type check(JCTree tree, Type owntype, int ownkind, int pkind, Type pt) { if (owntype.tag != ERROR && pt.tag != METHOD && pt.tag != FORALL) { if ((ownkind & ~pkind) == 0) { - owntype = chk.checkType(tree.pos(), owntype, pt); + owntype = chk.checkType(tree.pos(), owntype, pt, errKey); } else { log.error(tree.pos(), "unexpected.type", kindNames(pkind), @@ -239,7 +239,11 @@ public class Attr extends JCTree.Visitor { !((base == null || (base.getTag() == JCTree.IDENT && TreeInfo.name(base) == names._this)) && isAssignableAsBlankFinal(v, env)))) { - log.error(pos, "cant.assign.val.to.final.var", v); + if (v.isResourceVariable()) { //TWR resource + log.error(pos, "twr.resource.may.not.be.assigned", v); + } else { + log.error(pos, "cant.assign.val.to.final.var", v); + } } } @@ -372,6 +376,10 @@ public class Attr extends JCTree.Visitor { */ Type pt; + /** Visitor argument: the error key to be generated when a type error occurs + */ + String errKey; + /** Visitor result: the computed type. */ Type result; @@ -385,13 +393,19 @@ public class Attr extends JCTree.Visitor { * @param pt The prototype visitor argument. */ Type attribTree(JCTree tree, Env env, int pkind, Type pt) { + return attribTree(tree, env, pkind, pt, "incompatible.types"); + } + + Type attribTree(JCTree tree, Env env, int pkind, Type pt, String errKey) { Env prevEnv = this.env; int prevPkind = this.pkind; Type prevPt = this.pt; + String prevErrKey = this.errKey; try { this.env = env; this.pkind = pkind; this.pt = pt; + this.errKey = errKey; tree.accept(this); if (tree == breakTree) throw new BreakAttr(env); @@ -403,6 +417,7 @@ public class Attr extends JCTree.Visitor { this.env = prevEnv; this.pkind = prevPkind; this.pt = prevPt; + this.errKey = prevErrKey; } } @@ -412,6 +427,10 @@ public class Attr extends JCTree.Visitor { return attribTree(tree, env, VAL, pt.tag != ERROR ? pt : Type.noType); } + public Type attribExpr(JCTree tree, Env env, Type pt, String key) { + return attribTree(tree, env, VAL, pt.tag != ERROR ? pt : Type.noType, key); + } + /** Derived visitor method: attribute an expression tree with * no constraints on the computed type. */ @@ -976,14 +995,34 @@ public class Attr extends JCTree.Visitor { } public void visitTry(JCTry tree) { + // Create a new local environment with a local + Env localEnv = env.dup(tree, env.info.dup(env.info.scope.dup())); + boolean isTryWithResource = tree.resources.nonEmpty(); + // Create a nested environment for attributing the try block if needed + Env tryEnv = isTryWithResource ? + env.dup(tree, localEnv.info.dup(localEnv.info.scope.dup())) : + localEnv; + // Attribute resource declarations + for (JCTree resource : tree.resources) { + if (resource.getTag() == JCTree.VARDEF) { + attribStat(resource, tryEnv); + chk.checkType(resource, resource.type, syms.autoCloseableType, "twr.not.applicable.to.type"); + VarSymbol var = (VarSymbol)TreeInfo.symbolFor(resource); + var.setData(ElementKind.RESOURCE_VARIABLE); + } else { + attribExpr(resource, tryEnv, syms.autoCloseableType, "twr.not.applicable.to.type"); + } + } // Attribute body - attribStat(tree.body, env.dup(tree, env.info.dup())); + attribStat(tree.body, tryEnv); + if (isTryWithResource) + tryEnv.info.scope.leave(); // Attribute catch clauses for (List l = tree.catchers; l.nonEmpty(); l = l.tail) { JCCatch c = l.head; Env catchEnv = - env.dup(c, env.info.dup(env.info.scope.dup())); + localEnv.dup(c, localEnv.info.dup(localEnv.info.scope.dup())); Type ctype = attribStat(c.param, catchEnv); if (TreeInfo.isMultiCatch(c)) { //check that multi-catch parameter is marked as final @@ -1003,7 +1042,9 @@ public class Attr extends JCTree.Visitor { } // Attribute finalizer - if (tree.finalizer != null) attribStat(tree.finalizer, env); + if (tree.finalizer != null) attribStat(tree.finalizer, localEnv); + + localEnv.info.scope.leave(); result = null; } @@ -2139,6 +2180,15 @@ public class Attr extends JCTree.Visitor { checkAssignable(tree.pos(), v, tree.selected, env); } + if (sitesym != null && + sitesym.kind == VAR && + ((VarSymbol)sitesym).isResourceVariable() && + sym.kind == MTH && + sym.overrides(syms.autoCloseableClose, sitesym.type.tsym, types, true) && + env.info.lint.isEnabled(Lint.LintCategory.ARM)) { + log.warning(tree, "twr.explicit.close.call"); + } + // Disallow selecting a type from an expression if (isType(sym) && (sitesym==null || (sitesym.kind&(TYP|PCK)) == 0)) { tree.type = check(tree.selected, pt, diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java index 3b9999c1794..a306e357277 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java @@ -393,6 +393,10 @@ public class Check { * @param req The type that was required. */ Type checkType(DiagnosticPosition pos, Type found, Type req) { + return checkType(pos, found, req, "incompatible.types"); + } + + Type checkType(DiagnosticPosition pos, Type found, Type req, String errKey) { if (req.tag == ERROR) return req; if (found.tag == FORALL) @@ -411,7 +415,7 @@ public class Check { log.error(pos, "assignment.to.extends-bound", req); return types.createErrorType(found); } - return typeError(pos, diags.fragment("incompatible.types"), found, req); + return typeError(pos, diags.fragment(errKey), found, req); } /** Instantiate polymorphic type to some prototype, unless diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java index afec481986c..d105eb97564 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java @@ -28,6 +28,8 @@ package com.sun.tools.javac.comp; import java.util.HashMap; +import java.util.Map; +import java.util.LinkedHashMap; import com.sun.tools.javac.code.*; import com.sun.tools.javac.tree.*; @@ -265,6 +267,10 @@ public class Flow extends TreeScanner { */ List caught; + /** The list of unreferenced automatic resources. + */ + Map unrefdResources; + /** Set when processing a loop body the second time for DU analysis. */ boolean loopPassTwo = false; @@ -963,6 +969,7 @@ public class Flow extends TreeScanner { public void visitTry(JCTry tree) { List caughtPrev = caught; List thrownPrev = thrown; + Map unrefdResourcesPrev = unrefdResources; thrown = List.nil(); for (List l = tree.catchers; l.nonEmpty(); l = l.tail) { List subClauses = TreeInfo.isMultiCatch(l.head) ? @@ -977,6 +984,32 @@ public class Flow extends TreeScanner { pendingExits = new ListBuffer(); Bits initsTry = inits.dup(); uninitsTry = uninits.dup(); + unrefdResources = new LinkedHashMap(); + for (JCTree resource : tree.resources) { + if (resource instanceof JCVariableDecl) { + JCVariableDecl vdecl = (JCVariableDecl) resource; + visitVarDef(vdecl); + unrefdResources.put(vdecl.sym, vdecl); + } else if (resource instanceof JCExpression) { + scanExpr((JCExpression) resource); + } else { + throw new AssertionError(tree); // parser error + } + } + for (JCTree resource : tree.resources) { + MethodSymbol topCloseMethod = (MethodSymbol)syms.autoCloseableType.tsym.members().lookup(names.close).sym; + List closeableSupertypes = resource.type.isCompound() ? + types.interfaces(resource.type).prepend(types.supertype(resource.type)) : + List.of(resource.type); + for (Type sup : closeableSupertypes) { + if (types.asSuper(sup, syms.autoCloseableType.tsym) != null) { + MethodSymbol closeMethod = types.implementation(topCloseMethod, sup.tsym, types, true); + for (Type t : closeMethod.getThrownTypes()) { + markThrown(tree.body, t); + } + } + } + } scanStat(tree.body); List thrownInTry = thrown; thrown = thrownPrev; @@ -987,6 +1020,14 @@ public class Flow extends TreeScanner { Bits uninitsEnd = uninits; int nextadrCatch = nextadr; + if (!unrefdResources.isEmpty() && + lint.isEnabled(Lint.LintCategory.ARM)) { + for (Map.Entry e : unrefdResources.entrySet()) { + log.warning(e.getValue().pos(), + "automatic.resource.not.referenced", e.getKey()); + } + } + List caughtInTry = List.nil(); for (List l = tree.catchers; l.nonEmpty(); l = l.tail) { alive = true; @@ -1070,6 +1111,7 @@ public class Flow extends TreeScanner { while (exits.nonEmpty()) pendingExits.append(exits.next()); } uninitsTry.andSet(uninitsTryPrev).andSet(uninits); + unrefdResources = unrefdResourcesPrev; } public void visitConditional(JCConditional tree) { @@ -1293,8 +1335,16 @@ public class Flow extends TreeScanner { } public void visitIdent(JCIdent tree) { - if (tree.sym.kind == VAR) + if (tree.sym.kind == VAR) { checkInit(tree.pos(), (VarSymbol)tree.sym); + referenced(tree.sym); + } + } + + void referenced(Symbol sym) { + if (unrefdResources != null && unrefdResources.containsKey(sym)) { + unrefdResources.remove(sym); + } } public void visitTypeCast(JCTypeCast tree) { diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java index 44435b2dcfe..c5434eaf062 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java @@ -605,6 +605,23 @@ public class Lower extends TreeTranslator { s.enter(sym); } + /** Create a fresh synthetic name within a given scope - the unique name is + * obtained by appending '$' chars at the end of the name until no match + * is found. + * + * @param name base name + * @param s scope in which the name has to be unique + * @return fresh synthetic name + */ + private Name makeSyntheticName(Name name, Scope s) { + do { + name = name.append( + target.syntheticNameChar(), + names.empty); + } while (lookupSynthetic(name, s) != null); + return name; + } + /** Check whether synthetic symbols generated during lowering conflict * with user-defined symbols. * @@ -1299,6 +1316,11 @@ public class Lower extends TreeTranslator { */ Scope proxies; + /** A scope containing all unnamed resource variables/saved + * exception variables for translated TWR blocks + */ + Scope twrVars; + /** A stack containing the this$n field of the currently translated * classes (if needed) in innermost first order. * Inside a constructor, proxies and any this$n symbol are duplicated @@ -1400,6 +1422,122 @@ public class Lower extends TreeTranslator { } } + /** Optionally replace a try statement with an automatic resource + * management (ARM) block. + * @param tree The try statement to inspect. + * @return An ARM block, or the original try block if there are no + * resources to manage. + */ + JCTree makeArmTry(JCTry tree) { + make_at(tree.pos()); + twrVars = twrVars.dup(); + JCBlock armBlock = makeArmBlock(tree.resources, tree.body, 0); + if (tree.catchers.isEmpty() && tree.finalizer == null) + result = translate(armBlock); + else + result = translate(make.Try(armBlock, tree.catchers, tree.finalizer)); + twrVars = twrVars.leave(); + return result; + } + + private JCBlock makeArmBlock(List resources, JCBlock block, int depth) { + if (resources.isEmpty()) + return block; + + // Add resource declaration or expression to block statements + ListBuffer stats = new ListBuffer(); + JCTree resource = resources.head; + JCExpression expr = null; + if (resource instanceof JCVariableDecl) { + JCVariableDecl var = (JCVariableDecl) resource; + expr = make.Ident(var.sym).setType(resource.type); + stats.add(var); + } else { + assert resource instanceof JCExpression; + VarSymbol syntheticTwrVar = + new VarSymbol(SYNTHETIC | FINAL, + makeSyntheticName(names.fromString("twrVar" + + depth), twrVars), + (resource.type.tag == TypeTags.BOT) ? + syms.autoCloseableType : resource.type, + currentMethodSym); + twrVars.enter(syntheticTwrVar); + JCVariableDecl syntheticTwrVarDecl = + make.VarDef(syntheticTwrVar, (JCExpression)resource); + expr = (JCExpression)make.Ident(syntheticTwrVar); + stats.add(syntheticTwrVarDecl); + } + + // Add primaryException declaration + VarSymbol primaryException = + new VarSymbol(SYNTHETIC, + makeSyntheticName(names.fromString("primaryException" + + depth), twrVars), + syms.throwableType, + currentMethodSym); + twrVars.enter(primaryException); + JCVariableDecl primaryExceptionTreeDecl = make.VarDef(primaryException, makeNull()); + stats.add(primaryExceptionTreeDecl); + + // Create catch clause that saves exception and then rethrows it + VarSymbol param = + new VarSymbol(FINAL|SYNTHETIC, + names.fromString("t" + + target.syntheticNameChar()), + syms.throwableType, + currentMethodSym); + JCVariableDecl paramTree = make.VarDef(param, null); + JCStatement assign = make.Assignment(primaryException, make.Ident(param)); + JCStatement rethrowStat = make.Throw(make.Ident(param)); + JCBlock catchBlock = make.Block(0L, List.of(assign, rethrowStat)); + JCCatch catchClause = make.Catch(paramTree, catchBlock); + + int oldPos = make.pos; + make.at(TreeInfo.endPos(block)); + JCBlock finallyClause = makeArmFinallyClause(primaryException, expr); + make.at(oldPos); + JCTry outerTry = make.Try(makeArmBlock(resources.tail, block, depth + 1), + List.of(catchClause), + finallyClause); + stats.add(outerTry); + return make.Block(0L, stats.toList()); + } + + private JCBlock makeArmFinallyClause(Symbol primaryException, JCExpression resource) { + // primaryException.addSuppressedException(catchException); + VarSymbol catchException = + new VarSymbol(0, make.paramName(2), + syms.throwableType, + currentMethodSym); + JCStatement addSuppressionStatement = + make.Exec(makeCall(make.Ident(primaryException), + names.fromString("addSuppressedException"), + List.of(make.Ident(catchException)))); + + // try { resource.close(); } catch (e) { primaryException.addSuppressedException(e); } + JCBlock tryBlock = + make.Block(0L, List.of(makeResourceCloseInvocation(resource))); + JCVariableDecl catchExceptionDecl = make.VarDef(catchException, null); + JCBlock catchBlock = make.Block(0L, List.of(addSuppressionStatement)); + List catchClauses = List.of(make.Catch(catchExceptionDecl, catchBlock)); + JCTry tryTree = make.Try(tryBlock, catchClauses, null); + + // if (resource != null) resourceClose; + JCExpression nullCheck = makeBinary(JCTree.NE, + make.Ident(primaryException), + makeNull()); + JCIf closeIfStatement = make.If(nullCheck, + tryTree, + makeResourceCloseInvocation(resource)); + return make.Block(0L, List.of(closeIfStatement)); + } + + private JCStatement makeResourceCloseInvocation(JCExpression resource) { + // create resource.close() method invocation + JCExpression resourceClose = makeCall(resource, names.close, List.nil()); + return make.Exec(resourceClose); + } + /** Construct a tree that represents the outer instance * . Never pick the current `this'. * @param pos The source code position to be used for the tree. @@ -3405,6 +3543,15 @@ public class Lower extends TreeTranslator { result = tree; } + @Override + public void visitTry(JCTry tree) { + if (tree.resources.isEmpty()) { + super.visitTry(tree); + } else { + result = makeArmTry(tree); + } + } + /************************************************************************** * main method *************************************************************************/ @@ -3430,6 +3577,7 @@ public class Lower extends TreeTranslator { actualSymbols = new HashMap(); freevarCache = new HashMap>(); proxies = new Scope(syms.noSymbol); + twrVars = new Scope(syms.noSymbol); outerThisStack = List.nil(); accessNums = new HashMap(); accessSyms = new HashMap(); diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/TransTypes.java b/langtools/src/share/classes/com/sun/tools/javac/comp/TransTypes.java index cab86ec9b96..6530e09a14d 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/TransTypes.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/TransTypes.java @@ -535,6 +535,14 @@ public class TransTypes extends TreeTranslator { result = tree; } + public void visitTry(JCTry tree) { + tree.resources = translate(tree.resources, syms.autoCloseableType); + tree.body = translate(tree.body); + tree.catchers = translateCatchers(tree.catchers); + tree.finalizer = translate(tree.finalizer); + result = tree; + } + public void visitConditional(JCConditional tree) { tree.cond = translate(tree.cond, syms.booleanType); tree.truepart = translate(tree.truepart, erasure(tree.type)); diff --git a/langtools/src/share/classes/com/sun/tools/javac/jvm/CRTable.java b/langtools/src/share/classes/com/sun/tools/javac/jvm/CRTable.java index d49bf075ef3..e505129ef69 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/jvm/CRTable.java +++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/CRTable.java @@ -325,6 +325,7 @@ implements CRTFlags { public void visitTry(JCTry tree) { SourceRange sr = new SourceRange(startPos(tree), endPos(tree)); + sr.mergeWith(csp(tree.resources)); sr.mergeWith(csp(tree.body)); sr.mergeWith(cspCatchers(tree.catchers)); sr.mergeWith(csp(tree.finalizer)); diff --git a/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java b/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java index 32ae4d52a19..1d77d5362ca 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java +++ b/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java @@ -131,6 +131,7 @@ public class JavacParser implements Parser { this.allowForeach = source.allowForeach(); this.allowStaticImport = source.allowStaticImport(); this.allowAnnotations = source.allowAnnotations(); + this.allowTWR = source.allowTryWithResources(); this.allowDiamond = source.allowDiamond(); this.allowMulticatch = source.allowMulticatch(); this.allowTypeAnnotations = source.allowTypeAnnotations(); @@ -186,6 +187,10 @@ public class JavacParser implements Parser { */ boolean allowTypeAnnotations; + /** Switch: should we recognize automatic resource management? + */ + boolean allowTWR; + /** Switch: should we keep docComments? */ boolean keepDocComments; @@ -1846,6 +1851,7 @@ public class JavacParser implements Parser { * | WHILE ParExpression Statement * | DO Statement WHILE ParExpression ";" * | TRY Block ( Catches | [Catches] FinallyPart ) + * | TRY "(" ResourceSpecification ")" Block [Catches] [FinallyPart] * | SWITCH ParExpression "{" SwitchBlockStatementGroups "}" * | SYNCHRONIZED ParExpression Block * | RETURN [Expression] ";" @@ -1916,6 +1922,13 @@ public class JavacParser implements Parser { } case TRY: { S.nextToken(); + List resources = List.nil(); + if (S.token() == LPAREN) { + checkAutomaticResourceManagement(); + S.nextToken(); + resources = resources(); + accept(RPAREN); + } JCBlock body = block(); ListBuffer catchers = new ListBuffer(); JCBlock finalizer = null; @@ -1926,9 +1939,13 @@ public class JavacParser implements Parser { finalizer = block(); } } else { - log.error(pos, "try.without.catch.or.finally"); + if (allowTWR) { + if (resources.isEmpty()) + log.error(pos, "try.without.catch.finally.or.resource.decls"); + } else + log.error(pos, "try.without.catch.or.finally"); } - return F.at(pos).Try(body, catchers.toList(), finalizer); + return F.at(pos).Try(resources, body, catchers.toList(), finalizer); } case SWITCH: { S.nextToken(); @@ -2389,6 +2406,39 @@ public class JavacParser implements Parser { return toP(F.at(pos).VarDef(mods, name, type, null)); } + /** Resources = Resource { ";" Resources } + */ + List resources() { + ListBuffer defs = new ListBuffer(); + defs.append(resource()); + while (S.token() == SEMI) { + // All but last of multiple declarators subsume a semicolon + storeEnd(defs.elems.last(), S.endPos()); + S.nextToken(); + defs.append(resource()); + } + return defs.toList(); + } + + /** Resource = + * VariableModifiers Type VariableDeclaratorId = Expression + * | Expression + */ + JCTree resource() { + int pos = S.pos(); + if (S.token() == FINAL || S.token() == MONKEYS_AT) { + return variableDeclaratorRest(pos, optFinal(0), parseType(), + ident(), true, null); + } else { + JCExpression t = term(EXPR | TYPE); + if ((lastmode & TYPE) != 0 && S.token() == IDENTIFIER) + return variableDeclaratorRest(pos, toP(F.at(pos).Modifiers(Flags.FINAL)), t, + ident(), true, null); + else + return t; + } + } + /** CompilationUnit = [ { "@" Annotation } PACKAGE Qualident ";"] {ImportDeclaration} {TypeDeclaration} */ public JCTree.JCCompilationUnit parseCompilationUnit() { @@ -3220,6 +3270,12 @@ public class JavacParser implements Parser { if (!allowMulticatch) { log.error(S.pos(), "multicatch.not.supported.in.source", source.name); allowMulticatch = true; - } + } + } + void checkAutomaticResourceManagement() { + if (!allowTWR) { + log.error(S.pos(), "automatic.resource.management.not.supported.in.source", source.name); + allowTWR = true; + } } } diff --git a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties index 8fee222ad64..2e437a4f769 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties +++ b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties @@ -61,6 +61,8 @@ compiler.err.anon.class.impl.intf.no.typeargs=\ anonymous class implements interface; cannot have type arguments compiler.err.anon.class.impl.intf.no.qual.for.new=\ anonymous class implements interface; cannot have qualifier for new +compiler.misc.twr.not.applicable.to.type=\ + automatic resource management not applicable to variable type compiler.err.array.and.varargs=\ cannot declare both {0} and {1} in {2} compiler.err.array.dimension.missing=\ @@ -172,6 +174,8 @@ compiler.err.except.never.thrown.in.try=\ compiler.err.final.parameter.may.not.be.assigned=\ final parameter {0} may not be assigned +compiler.err.twr.resource.may.not.be.assigned=\ + automatic resource {0} may not be assigned compiler.err.multicatch.parameter.may.not.be.assigned=\ multi-catch parameter {0} may not be assigned compiler.err.multicatch.param.must.be.final=\ @@ -448,6 +452,8 @@ compiler.err.throws.not.allowed.in.intf.annotation=\ throws clause not allowed in @interface members compiler.err.try.without.catch.or.finally=\ ''try'' without ''catch'' or ''finally'' +compiler.err.try.without.catch.finally.or.resource.decls=\ + ''try'' without ''catch'', ''finally'' or resource declarations compiler.err.type.doesnt.take.params=\ type {0} does not take parameters compiler.err.type.var.cant.be.deref=\ @@ -797,6 +803,10 @@ compiler.warn.proc.unclosed.type.files=\ compiler.warn.proc.unmatched.processor.options=\ The following options were not recognized by any processor: ''{0}'' +compiler.warn.twr.explicit.close.call=\ + [arm] explicit call to close() on an automatic resource +compiler.warn.automatic.resource.not.referenced=\ + [arm] automatic resource {0} is never referenced in body of corresponding try statement compiler.warn.unchecked.assign=\ [unchecked] unchecked assignment: {0} to {1} compiler.warn.unchecked.assign.to.var=\ @@ -1217,6 +1227,10 @@ compiler.err.unsupported.underscore.lit=\ underscores in literals are not supported in -source {0}\n\ (use -source 7 or higher to enable underscores in literals) +compiler.err.automatic.resource.management.not.supported.in.source=\ + automatic resource management is not supported in -source {0}\n\ +(use -source 7 or higher to enable automatic resource management) + compiler.warn.enum.as.identifier=\ as of release 5, ''enum'' is a keyword, and may not be used as an identifier\n\ (use -source 5 or higher to use ''enum'' as a keyword) diff --git a/langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java b/langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java index bf3f59292f2..64a991b03f7 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java @@ -1021,10 +1021,15 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { public JCBlock body; public List catchers; public JCBlock finalizer; - protected JCTry(JCBlock body, List catchers, JCBlock finalizer) { + public List resources; + protected JCTry(List resources, + JCBlock body, + List catchers, + JCBlock finalizer) { this.body = body; this.catchers = catchers; this.finalizer = finalizer; + this.resources = resources; } @Override public void accept(Visitor v) { v.visitTry(this); } @@ -1040,6 +1045,10 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { return v.visitTry(this, d); } @Override + public List getResources() { + return resources; + } + @Override public int getTag() { return TRY; } @@ -2162,6 +2171,10 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { JCCase Case(JCExpression pat, List stats); JCSynchronized Synchronized(JCExpression lock, JCBlock body); JCTry Try(JCBlock body, List catchers, JCBlock finalizer); + JCTry Try(List resources, + JCBlock body, + List catchers, + JCBlock finalizer); JCCatch Catch(JCVariableDecl param, JCBlock body); JCConditional Conditional(JCExpression cond, JCExpression thenpart, diff --git a/langtools/src/share/classes/com/sun/tools/javac/tree/Pretty.java b/langtools/src/share/classes/com/sun/tools/javac/tree/Pretty.java index 34e221ee528..66f6e56104d 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/tree/Pretty.java +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/Pretty.java @@ -691,6 +691,19 @@ public class Pretty extends JCTree.Visitor { public void visitTry(JCTry tree) { try { print("try "); + if (tree.resources.nonEmpty()) { + print("("); + boolean first = true; + for (JCTree var : tree.resources) { + if (!first) { + println(); + indent(); + } + printStat(var); + first = false; + } + print(") "); + } printStat(tree.body); for (List l = tree.catchers; l.nonEmpty(); l = l.tail) { printStat(l.head); diff --git a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeCopier.java b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeCopier.java index e3977f66559..6abbfdbec9c 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeCopier.java +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeCopier.java @@ -332,10 +332,11 @@ public class TreeCopier

    implements TreeVisitor { public JCTree visitTry(TryTree node, P p) { JCTry t = (JCTry) node; + List resources = copy(t.resources, p); JCBlock body = copy(t.body, p); List catchers = copy(t.catchers, p); JCBlock finalizer = copy(t.finalizer, p); - return M.at(t.pos).Try(body, catchers, finalizer); + return M.at(t.pos).Try(resources, body, catchers, finalizer); } public JCTree visitParameterizedType(ParameterizedTypeTree node, P p) { diff --git a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeMaker.java b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeMaker.java index 5ef56c86d26..eef94a62b32 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeMaker.java +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeMaker.java @@ -269,7 +269,14 @@ public class TreeMaker implements JCTree.Factory { } public JCTry Try(JCBlock body, List catchers, JCBlock finalizer) { - JCTry tree = new JCTry(body, catchers, finalizer); + return Try(List.nil(), body, catchers, finalizer); + } + + public JCTry Try(List resources, + JCBlock body, + List catchers, + JCBlock finalizer) { + JCTry tree = new JCTry(resources, body, catchers, finalizer); tree.pos = pos; return tree; } diff --git a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeScanner.java b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeScanner.java index d0bcfb912f1..53eb5118fb3 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeScanner.java +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeScanner.java @@ -147,6 +147,7 @@ public class TreeScanner extends Visitor { } public void visitTry(JCTry tree) { + scan(tree.resources); scan(tree.body); scan(tree.catchers); scan(tree.finalizer); diff --git a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeTranslator.java b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeTranslator.java index e08238267b8..ffb219b6a63 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeTranslator.java +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeTranslator.java @@ -212,6 +212,7 @@ public class TreeTranslator extends JCTree.Visitor { } public void visitTry(JCTry tree) { + tree.resources = translate(tree.resources); tree.body = translate(tree.body); tree.catchers = translateCatchers(tree.catchers); tree.finalizer = translate(tree.finalizer); diff --git a/langtools/src/share/classes/com/sun/tools/javac/util/Names.java b/langtools/src/share/classes/com/sun/tools/javac/util/Names.java index 3bfa9a35743..095a7e3f0ee 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/util/Names.java +++ b/langtools/src/share/classes/com/sun/tools/javac/util/Names.java @@ -148,6 +148,8 @@ public class Names { public final Name getDeclaringClass; public final Name ex; public final Name finalize; + public final Name java_lang_AutoCloseable; + public final Name close; public final Name.Table table; @@ -263,6 +265,9 @@ public class Names { getDeclaringClass = fromString("getDeclaringClass"); ex = fromString("ex"); finalize = fromString("finalize"); + + java_lang_AutoCloseable = fromString("java.lang.AutoCloseable"); + close = fromString("close"); } protected Name.Table createTable(Options options) { diff --git a/langtools/test/tools/javac/TryWithResources/ArmLint.java b/langtools/test/tools/javac/TryWithResources/ArmLint.java new file mode 100644 index 00000000000..2a5a22392ba --- /dev/null +++ b/langtools/test/tools/javac/TryWithResources/ArmLint.java @@ -0,0 +1,55 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6911256 6964740 6965277 6967065 + * @author Joseph D. Darcy + * @summary Check that -Xlint:arm warnings are generated as expected + * @compile/ref=ArmLint.out -Xlint:arm,deprecation -XDrawDiagnostics ArmLint.java + */ + +class ArmLint implements AutoCloseable { + private static void test1() { + try(ArmLint r1 = new ArmLint(); + ArmLint r2 = new ArmLint(); + ArmLint r3 = new ArmLint()) { + r1.close(); // The resource's close + r2.close(42); // *Not* the resource's close + // r3 not referenced + } + + } + + @SuppressWarnings("arm") + private static void test2() { + try(@SuppressWarnings("deprecation") AutoCloseable r4 = + new DeprecatedAutoCloseable()) { + // r4 not referenced + } catch(Exception e) { + ; + } + } + + /** + * The AutoCloseable method of a resource. + */ + @Override + public void close () { + return; + } + + /** + * Not the AutoCloseable method of a resource. + */ + public void close (int arg) { + return; + } +} + +@Deprecated +class DeprecatedAutoCloseable implements AutoCloseable { + public DeprecatedAutoCloseable(){super();} + + @Override + public void close () { + return; + } +} diff --git a/langtools/test/tools/javac/TryWithResources/ArmLint.out b/langtools/test/tools/javac/TryWithResources/ArmLint.out new file mode 100644 index 00000000000..f60161a5257 --- /dev/null +++ b/langtools/test/tools/javac/TryWithResources/ArmLint.out @@ -0,0 +1,3 @@ +ArmLint.java:14:15: compiler.warn.twr.explicit.close.call +ArmLint.java:13:13: compiler.warn.automatic.resource.not.referenced: r3 +2 warnings diff --git a/langtools/test/tools/javac/TryWithResources/BadTwr.java b/langtools/test/tools/javac/TryWithResources/BadTwr.java new file mode 100644 index 00000000000..71286458e4e --- /dev/null +++ b/langtools/test/tools/javac/TryWithResources/BadTwr.java @@ -0,0 +1,36 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6911256 6964740 + * @author Joseph D. Darcy + * @summary Verify bad TWRs don't compile + * @compile/fail -source 6 TwrFlow.java + * @compile/fail/ref=BadTwr.out -XDrawDiagnostics BadTwr.java + */ + +public class BadTwr implements AutoCloseable { + public static void main(String... args) { + // illegal repeated name + try(BadTwr r1 = new BadTwr(); BadTwr r1 = new BadTwr()) { + System.out.println(r1.toString()); + } + + // illegal duplicate name of method argument + try(BadTwr args = new BadTwr()) { + System.out.println(args.toString()); + final BadTwr thatsIt = new BadTwr(); + thatsIt = null; + } + + try(BadTwr name = new BadTwr()) { + // illegal duplicate name of enclosing try + try(BadTwr name = new BadTwr()) { + System.out.println(name.toString()); + } + } + + } + + public void close() { + ; + } +} diff --git a/langtools/test/tools/javac/TryWithResources/BadTwr.out b/langtools/test/tools/javac/TryWithResources/BadTwr.out new file mode 100644 index 00000000000..3ed73139157 --- /dev/null +++ b/langtools/test/tools/javac/TryWithResources/BadTwr.out @@ -0,0 +1,5 @@ +BadTwr.java:13:39: compiler.err.already.defined: r1, main(java.lang.String...) +BadTwr.java:18:13: compiler.err.already.defined: args, main(java.lang.String...) +BadTwr.java:21:13: compiler.err.cant.assign.val.to.final.var: thatsIt +BadTwr.java:26:17: compiler.err.already.defined: name, main(java.lang.String...) +4 errors diff --git a/langtools/test/tools/javac/TryWithResources/BadTwrSyntax.java b/langtools/test/tools/javac/TryWithResources/BadTwrSyntax.java new file mode 100644 index 00000000000..3dbe2c4f5e8 --- /dev/null +++ b/langtools/test/tools/javac/TryWithResources/BadTwrSyntax.java @@ -0,0 +1,22 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6911256 6964740 + * @author Joseph D. Darcy + * @summary Verify bad TWRs don't compile + * @compile/fail -source 6 BadTwrSyntax.java + * @compile/fail/ref=BadTwrSyntax.out -XDrawDiagnostics BadTwrSyntax.java + */ + +import java.io.IOException; +public class BadTwrSyntax implements AutoCloseable { + public static void main(String... args) throws Exception { + // illegal semicolon ending resources + try(BadTwr twrflow = new BadTwr();) { + System.out.println(twrflow.toString()); + } + } + + public void close() { + ; + } +} diff --git a/langtools/test/tools/javac/TryWithResources/BadTwrSyntax.out b/langtools/test/tools/javac/TryWithResources/BadTwrSyntax.out new file mode 100644 index 00000000000..df925e04eb9 --- /dev/null +++ b/langtools/test/tools/javac/TryWithResources/BadTwrSyntax.out @@ -0,0 +1,2 @@ +BadTwrSyntax.java:14:43: compiler.err.illegal.start.of.expr +1 error diff --git a/langtools/test/tools/javac/TryWithResources/DuplicateResource.java b/langtools/test/tools/javac/TryWithResources/DuplicateResource.java new file mode 100644 index 00000000000..ca2f554244f --- /dev/null +++ b/langtools/test/tools/javac/TryWithResources/DuplicateResource.java @@ -0,0 +1,65 @@ +/* + * 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 6911256 6964740 6965277 + * @author Maurizio Cimadamore + * @summary Check that lowered arm block does not end up creating resource twice + */ + +import java.util.ArrayList; + +public class DuplicateResource { + + static class TestResource implements AutoCloseable { + TestResource() { + resources.add(this); + } + boolean isClosed = false; + public void close() throws Exception { + isClosed = true; + } + } + + static ArrayList resources = new ArrayList(); + + public static void main(String[] args) { + try(new TestResource()) { + //do something + } catch (Exception e) { + throw new AssertionError("Shouldn't reach here", e); + } + check(); + } + + public static void check() { + if (resources.size() != 1) { + throw new AssertionError("Expected one resource, found: " + resources.size()); + } + TestResource resource = resources.get(0); + if (!resource.isClosed) { + throw new AssertionError("Resource used in ARM block has not been automatically closed"); + } + } +} diff --git a/langtools/test/tools/javac/TryWithResources/DuplicateResourceDecl.java b/langtools/test/tools/javac/TryWithResources/DuplicateResourceDecl.java new file mode 100644 index 00000000000..52b8d243eee --- /dev/null +++ b/langtools/test/tools/javac/TryWithResources/DuplicateResourceDecl.java @@ -0,0 +1,20 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6911256 6964740 6965277 + * @author Maurizio Cimadamore + * @summary Check that resource variable is not accessible from catch/finally clause + * @compile/fail/ref=DuplicateResourceDecl.out -XDrawDiagnostics DuplicateResourceDecl.java + */ + +class DuplicateResourceDecl { + + public static void main(String[] args) { + try(MyResource c = new MyResource();MyResource c = new MyResource()) { + //do something + } catch (Exception e) { } + } + + static class MyResource implements AutoCloseable { + public void close() throws Exception {} + } +} diff --git a/langtools/test/tools/javac/TryWithResources/DuplicateResourceDecl.out b/langtools/test/tools/javac/TryWithResources/DuplicateResourceDecl.out new file mode 100644 index 00000000000..463b10be558 --- /dev/null +++ b/langtools/test/tools/javac/TryWithResources/DuplicateResourceDecl.out @@ -0,0 +1,2 @@ +DuplicateResourceDecl.java:12:45: compiler.err.already.defined: c, main(java.lang.String[]) +1 error diff --git a/langtools/test/tools/javac/TryWithResources/ImplicitFinal.java b/langtools/test/tools/javac/TryWithResources/ImplicitFinal.java new file mode 100644 index 00000000000..ebcf0aff3f2 --- /dev/null +++ b/langtools/test/tools/javac/TryWithResources/ImplicitFinal.java @@ -0,0 +1,27 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6911256 6964740 6965277 + * @author Maurizio Cimadamore + * @summary Test that resource variables are implicitly final + * @compile/fail/ref=ImplicitFinal.out -XDrawDiagnostics ImplicitFinal.java + */ + +import java.io.IOException; + +class ImplicitFinal implements AutoCloseable { + public static void main(String... args) { + try(ImplicitFinal r = new ImplicitFinal()) { + r = null; //disallowed + } catch (IOException ioe) { // Not reachable + throw new AssertionError("Shouldn't reach here", ioe); + } + } + + + // A close method, but the class is not Closeable or + // AutoCloseable. + + public void close() throws IOException { + throw new IOException(); + } +} diff --git a/langtools/test/tools/javac/TryWithResources/ImplicitFinal.out b/langtools/test/tools/javac/TryWithResources/ImplicitFinal.out new file mode 100644 index 00000000000..0e33814b83f --- /dev/null +++ b/langtools/test/tools/javac/TryWithResources/ImplicitFinal.out @@ -0,0 +1,2 @@ +ImplicitFinal.java:14:13: compiler.err.twr.resource.may.not.be.assigned: r +1 error diff --git a/langtools/test/tools/javac/TryWithResources/PlainTry.java b/langtools/test/tools/javac/TryWithResources/PlainTry.java new file mode 100644 index 00000000000..fad4ca8c054 --- /dev/null +++ b/langtools/test/tools/javac/TryWithResources/PlainTry.java @@ -0,0 +1,15 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6911256 6964740 + * @author Joseph D. Darcy + * @summary Test error messages for an unadorned try + * @compile/fail/ref=PlainTry6.out -XDrawDiagnostics -source 6 PlainTry.java + * @compile/fail/ref=PlainTry.out -XDrawDiagnostics PlainTry.java + */ +public class PlainTry { + public static void main(String... args) { + try { + ; + } + } +} diff --git a/langtools/test/tools/javac/TryWithResources/PlainTry.out b/langtools/test/tools/javac/TryWithResources/PlainTry.out new file mode 100644 index 00000000000..2751797eeb6 --- /dev/null +++ b/langtools/test/tools/javac/TryWithResources/PlainTry.out @@ -0,0 +1,2 @@ +PlainTry.java:11:9: compiler.err.try.without.catch.finally.or.resource.decls +1 error diff --git a/langtools/test/tools/javac/TryWithResources/PlainTry6.out b/langtools/test/tools/javac/TryWithResources/PlainTry6.out new file mode 100644 index 00000000000..5a8067d66fb --- /dev/null +++ b/langtools/test/tools/javac/TryWithResources/PlainTry6.out @@ -0,0 +1,2 @@ +PlainTry.java:11:9: compiler.err.try.without.catch.or.finally +1 error diff --git a/langtools/test/tools/javac/TryWithResources/ResourceOutsideTry.java b/langtools/test/tools/javac/TryWithResources/ResourceOutsideTry.java new file mode 100644 index 00000000000..16e5d3471e1 --- /dev/null +++ b/langtools/test/tools/javac/TryWithResources/ResourceOutsideTry.java @@ -0,0 +1,23 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6911256 6964740 6965277 + * @author Maurizio Cimadamore + * @summary Check that resource variable is not accessible from catch/finally clause + * @compile/fail/ref=ResourceOutsideTry.out -XDrawDiagnostics ResourceOutsideTry.java + */ + +class ResourceOutsideTry { + void test() { + try(MyResource c = new MyResource()) { + //do something + } catch (Exception e) { + c.test(); + } finally { + c.test(); + } + } + static class MyResource implements AutoCloseable { + public void close() throws Exception {} + void test() {} + } +} diff --git a/langtools/test/tools/javac/TryWithResources/ResourceOutsideTry.out b/langtools/test/tools/javac/TryWithResources/ResourceOutsideTry.out new file mode 100644 index 00000000000..e043b792dec --- /dev/null +++ b/langtools/test/tools/javac/TryWithResources/ResourceOutsideTry.out @@ -0,0 +1,3 @@ +ResourceOutsideTry.java:14:13: compiler.err.cant.resolve.location: kindname.variable, c, , , kindname.class, ResourceOutsideTry +ResourceOutsideTry.java:16:13: compiler.err.cant.resolve.location: kindname.variable, c, , , kindname.class, ResourceOutsideTry +2 errors diff --git a/langtools/test/tools/javac/TryWithResources/ResourceTypeVar.java b/langtools/test/tools/javac/TryWithResources/ResourceTypeVar.java new file mode 100644 index 00000000000..2c9837318be --- /dev/null +++ b/langtools/test/tools/javac/TryWithResources/ResourceTypeVar.java @@ -0,0 +1,43 @@ +/* + * 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 6911256 6964740 6965277 + * @author Maurizio Cimadamore + * @summary Resource of a type-variable type crashes Flow + * @compile ResourceTypeVar.java + */ + +class ResourceTypeVar { + + public void test() { + try(X armflow = getX()) { + //do something + } catch (Exception e) { // Not reachable + throw new AssertionError("Shouldn't reach here", e); + } + } + + X getX() { return null; } +} diff --git a/langtools/test/tools/javac/TryWithResources/TwrFlow.java b/langtools/test/tools/javac/TryWithResources/TwrFlow.java new file mode 100644 index 00000000000..01f8b1aa2e9 --- /dev/null +++ b/langtools/test/tools/javac/TryWithResources/TwrFlow.java @@ -0,0 +1,39 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6911256 6964740 + * @author Joseph D. Darcy + * @summary Test exception analysis of ARM blocks + * @compile/fail/ref=TwrFlow.out -XDrawDiagnostics TwrFlow.java + */ + +import java.io.IOException; +public class TwrFlow implements AutoCloseable { + public static void main(String... args) { + try(TwrFlow armflow = new TwrFlow()) { + System.out.println(armflow.toString()); + } catch (IOException ioe) { // Not reachable + throw new AssertionError("Shouldn't reach here", ioe); + } + // CustomCloseException should be caught or added to throws clause + + // Also check behavior on a resource expression rather than a + // declaration. + TwrFlow armflowexpr = new TwrFlow(); + try(armflowexpr) { + System.out.println(armflowexpr.toString()); + } catch (IOException ioe) { // Not reachable + throw new AssertionError("Shouldn't reach here", ioe); + } + // CustomCloseException should be caught or added to throws clause + } + + /* + * A close method, but the class is not Closeable or + * AutoCloseable. + */ + public void close() throws CustomCloseException { + throw new CustomCloseException(); + } +} + +class CustomCloseException extends Exception {} diff --git a/langtools/test/tools/javac/TryWithResources/TwrFlow.out b/langtools/test/tools/javac/TryWithResources/TwrFlow.out new file mode 100644 index 00000000000..dd0e61aebf4 --- /dev/null +++ b/langtools/test/tools/javac/TryWithResources/TwrFlow.out @@ -0,0 +1,5 @@ +TwrFlow.java:14:11: compiler.err.except.never.thrown.in.try: java.io.IOException +TwrFlow.java:24:11: compiler.err.except.never.thrown.in.try: java.io.IOException +TwrFlow.java:12:46: compiler.err.unreported.exception.need.to.catch.or.throw: CustomCloseException +TwrFlow.java:22:26: compiler.err.unreported.exception.need.to.catch.or.throw: CustomCloseException +4 errors diff --git a/langtools/test/tools/javac/TryWithResources/TwrInference.java b/langtools/test/tools/javac/TryWithResources/TwrInference.java new file mode 100644 index 00000000000..87187e43ffe --- /dev/null +++ b/langtools/test/tools/javac/TryWithResources/TwrInference.java @@ -0,0 +1,43 @@ +/* + * 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 6911256 6964740 6965277 + * @author Maurizio Cimadamore + * @summary Verify that method type-inference works as expected in TWR context + * @compile TwrInference.java + */ + +class TwrInference { + + public void test() { + try(getX()) { + //do something + } catch (Exception e) { // Not reachable + throw new AssertionError("Shouldn't reach here", e); + } + } + + X getX() { return null; } +} diff --git a/langtools/test/tools/javac/TryWithResources/TwrIntersection.java b/langtools/test/tools/javac/TryWithResources/TwrIntersection.java new file mode 100644 index 00000000000..4e3a1303736 --- /dev/null +++ b/langtools/test/tools/javac/TryWithResources/TwrIntersection.java @@ -0,0 +1,47 @@ +/* + * 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 6911256 6964740 6965277 + * @author Maurizio Cimadamore + * @summary Resource of an intersection type crashes Flow + * @compile TwrIntersection.java + */ + +interface MyCloseable extends AutoCloseable { + void close() throws java.io.IOException; +} + +class ResourceTypeVar { + + public void test() { + try(getX()) { + //do something + } catch (java.io.IOException e) { // Not reachable + throw new AssertionError("Shouldn't reach here", e); + } + } + + X getX() { return null; } +} diff --git a/langtools/test/tools/javac/TryWithResources/TwrIntersection02.java b/langtools/test/tools/javac/TryWithResources/TwrIntersection02.java new file mode 100644 index 00000000000..3cefe6b505c --- /dev/null +++ b/langtools/test/tools/javac/TryWithResources/TwrIntersection02.java @@ -0,0 +1,37 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6911256 6964740 6965277 + * @author Maurizio Cimadamore + * @summary Check that resources of an intersection type forces union of exception types + * to be caught outside twr block + * @compile/fail/ref=TwrIntersection02.out -XDrawDiagnostics TwrIntersection02.java + */ + +class TwrIntersection02 { + + static class Exception1 extends Exception {} + static class Exception2 extends Exception {} + + + interface MyResource1 extends AutoCloseable { + void close() throws Exception1; + } + + interface MyResource2 extends AutoCloseable { + void close() throws Exception2; + } + + public void test1() throws Exception1 { + try(getX()) { + //do something + } + } + + public void test2() throws Exception2 { + try(getX()) { + //do something + } + } + + X getX() { return null; } +} diff --git a/langtools/test/tools/javac/TryWithResources/TwrIntersection02.out b/langtools/test/tools/javac/TryWithResources/TwrIntersection02.out new file mode 100644 index 00000000000..69a5f3f1c78 --- /dev/null +++ b/langtools/test/tools/javac/TryWithResources/TwrIntersection02.out @@ -0,0 +1,3 @@ +TwrIntersection02.java:25:21: compiler.err.unreported.exception.need.to.catch.or.throw: TwrIntersection02.Exception2 +TwrIntersection02.java:31:21: compiler.err.unreported.exception.need.to.catch.or.throw: TwrIntersection02.Exception1 +2 errors diff --git a/langtools/test/tools/javac/TryWithResources/TwrMultiCatch.java b/langtools/test/tools/javac/TryWithResources/TwrMultiCatch.java new file mode 100644 index 00000000000..8b49837d80e --- /dev/null +++ b/langtools/test/tools/javac/TryWithResources/TwrMultiCatch.java @@ -0,0 +1,81 @@ +/* + * 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 6911256 6964740 + * @author Joseph D. Darcy + * @summary Test that TWR and multi-catch play well together + * @compile TwrMultiCatch.java + * @run main TwrMultiCatch + */ + +import java.io.IOException; +public class TwrMultiCatch implements AutoCloseable { + private final Class exceptionClass; + + private TwrMultiCatch(Class exceptionClass) { + this.exceptionClass = exceptionClass; + } + + public static void main(String... args) { + test(new TwrMultiCatch(CustomCloseException1.class), + CustomCloseException1.class); + + test(new TwrMultiCatch(CustomCloseException2.class), + CustomCloseException2.class); + } + + private static void test(TwrMultiCatch twrMultiCatch, + Class expected) { + try(twrMultiCatch) { + System.out.println(twrMultiCatch.toString()); + } catch (final CustomCloseException1 | + CustomCloseException2 exception) { + if (!exception.getClass().equals(expected) ) { + throw new RuntimeException("Unexpected catch!"); + } + } + } + + public void close() throws CustomCloseException1, CustomCloseException2 { + Throwable t; + try { + t = exceptionClass.newInstance(); + } catch(ReflectiveOperationException rfe) { + throw new RuntimeException(rfe); + } + + try { + throw t; + } catch (final CustomCloseException1 | + CustomCloseException2 exception) { + throw exception; + } catch (Throwable throwable) { + throw new RuntimeException(throwable); + } + } +} + +class CustomCloseException1 extends Exception {} +class CustomCloseException2 extends Exception {} diff --git a/langtools/test/tools/javac/TryWithResources/TwrOnNonResource.java b/langtools/test/tools/javac/TryWithResources/TwrOnNonResource.java new file mode 100644 index 00000000000..5673243ae95 --- /dev/null +++ b/langtools/test/tools/javac/TryWithResources/TwrOnNonResource.java @@ -0,0 +1,42 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6911256 6964740 + * @author Joseph D. Darcy + * @summary Verify invalid TWR block is not accepted. + * @compile/fail -source 6 TwrOnNonResource.java + * @compile/fail/ref=TwrOnNonResource.out -XDrawDiagnostics TwrOnNonResource.java + */ + +class TwrOnNonResource { + public static void main(String... args) { + try(TwrOnNonResource aonr = new TwrOnNonResource()) { + System.out.println(aonr.toString()); + } + try(TwrOnNonResource aonr = new TwrOnNonResource()) { + System.out.println(aonr.toString()); + } finally {;} + try(TwrOnNonResource aonr = new TwrOnNonResource()) { + System.out.println(aonr.toString()); + } catch (Exception e) {;} + + // Also check expression form + TwrOnNonResource aonr = new TwrOnNonResource(); + try(aonr) { + System.out.println(aonr.toString()); + } + try(aonr) { + System.out.println(aonr.toString()); + } finally {;} + try(aonr) { + System.out.println(aonr.toString()); + } catch (Exception e) {;} + } + + /* + * A close method, but the class is not Closeable or + * AutoCloseable. + */ + public void close() { + throw new AssertionError("I'm not Closable!"); + } +} diff --git a/langtools/test/tools/javac/TryWithResources/TwrOnNonResource.out b/langtools/test/tools/javac/TryWithResources/TwrOnNonResource.out new file mode 100644 index 00000000000..a894aff7ffb --- /dev/null +++ b/langtools/test/tools/javac/TryWithResources/TwrOnNonResource.out @@ -0,0 +1,7 @@ +TwrOnNonResource.java:12:13: compiler.err.prob.found.req: (compiler.misc.twr.not.applicable.to.type), TwrOnNonResource, java.lang.AutoCloseable +TwrOnNonResource.java:15:13: compiler.err.prob.found.req: (compiler.misc.twr.not.applicable.to.type), TwrOnNonResource, java.lang.AutoCloseable +TwrOnNonResource.java:18:13: compiler.err.prob.found.req: (compiler.misc.twr.not.applicable.to.type), TwrOnNonResource, java.lang.AutoCloseable +TwrOnNonResource.java:24:13: compiler.err.prob.found.req: (compiler.misc.twr.not.applicable.to.type), TwrOnNonResource, java.lang.AutoCloseable +TwrOnNonResource.java:27:13: compiler.err.prob.found.req: (compiler.misc.twr.not.applicable.to.type), TwrOnNonResource, java.lang.AutoCloseable +TwrOnNonResource.java:30:13: compiler.err.prob.found.req: (compiler.misc.twr.not.applicable.to.type), TwrOnNonResource, java.lang.AutoCloseable +6 errors diff --git a/langtools/test/tools/javac/TryWithResources/TwrTests.java b/langtools/test/tools/javac/TryWithResources/TwrTests.java new file mode 100644 index 00000000000..c3ca6176573 --- /dev/null +++ b/langtools/test/tools/javac/TryWithResources/TwrTests.java @@ -0,0 +1,742 @@ +/* + * 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 + * 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 6911256 6964740 + * @summary Tests of generated TWR code. + */ + +import java.util.List; +import java.util.ArrayList; + +public class TwrTests { + public static void main(String[] args) { + testCreateFailure1(); + testCreateFailure2(); + testCreateFailure2Nested(); + testCreateFailure3(); + testCreateFailure3Nested(); + testCreateFailure4(); + testCreateFailure4Nested(); + testCreateFailure5(); + testCreateFailure5Nested(); + + testCreateSuccess1(); + testCreateSuccess2(); + testCreateSuccess2Nested(); + testCreateSuccess3(); + testCreateSuccess3Nested(); + testCreateSuccess4(); + testCreateSuccess4Nested(); + testCreateSuccess5(); + testCreateSuccess5Nested(); + } + + /* + * The following tests simulate a creation failure of every possible + * resource in an TWR block, and check to make sure that the failure + * prevents creation of subsequent resources, and that all created + * resources are properly closed, even if one or more of the close + * attempts fails. + */ + + public static void testCreateFailure1() { + int creationFailuresDetected = 0; + List closedList = new ArrayList(0); + try (Resource r0 = createResource(0, 0, 0, closedList)) { + throw new AssertionError("Resource creation succeeded"); + } catch (Resource.CreateFailException e) { + creationFailuresDetected++; + if (e.resourceId() != 0) { + throw new AssertionError("Wrong resource creation " + + e.resourceId() + " failed"); + } + } catch (Resource.CloseFailException e) { + throw new AssertionError("Unexpected CloseFailException: " + e.resourceId()); + } + checkForSingleCreationFailure(creationFailuresDetected); + checkClosedList(closedList, 0); + } + + public static void testCreateFailure2() { + for (int createFailureId = 0; createFailureId < 2; createFailureId++) { + for (int bitMap = 0, n = 1 << createFailureId; bitMap < n; bitMap++) { + int creationFailuresDetected = 0; + List closedList = new ArrayList(); + try (Resource r0 = createResource(0, createFailureId, bitMap, closedList); + Resource r1 = createResource(1, createFailureId, bitMap, closedList)) { + throw new AssertionError("Entire resource creation succeeded"); + } catch (Resource.CreateFailException e) { + creationFailuresDetected++; + checkCreateFailureId(e.resourceId(), createFailureId); + checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap); + } catch (Resource.CloseFailException e) { + throw new AssertionError("Secondary exception suppression failed"); + } + checkForSingleCreationFailure(creationFailuresDetected); + checkClosedList(closedList, createFailureId); + } + } + } + + public static void testCreateFailure2Nested() { + for (int createFailureId = 0; createFailureId < 2; createFailureId++) { + for (int bitMap = 0, n = 1 << createFailureId; bitMap < n; bitMap++) { + int creationFailuresDetected = 0; + List closedList = new ArrayList(); + try (Resource r0 = createResource(0, createFailureId, bitMap, closedList)) { + try(Resource r1 = createResource(1, createFailureId, bitMap, closedList)) { + throw new AssertionError("Entire resource creation succeeded"); + } + } catch (Resource.CreateFailException e) { + creationFailuresDetected++; + checkCreateFailureId(e.resourceId(), createFailureId); + checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap); + } catch (Resource.CloseFailException e) { + throw new AssertionError("Secondary exception suppression failed"); + } + checkForSingleCreationFailure(creationFailuresDetected); + checkClosedList(closedList, createFailureId); + } + } + } + + public static void testCreateFailure3() { + for (int createFailureId = 0; createFailureId < 3; createFailureId++) { + for (int bitMap = 0, n = 1 << createFailureId; bitMap < n; bitMap++) { + int creationFailuresDetected = 0; + List closedList = new ArrayList(); + try (Resource r0 = createResource(0, createFailureId, bitMap, closedList); + Resource r1 = createResource(1, createFailureId, bitMap, closedList); + Resource r2 = createResource(2, createFailureId, bitMap, closedList)) { + throw new AssertionError("Entire resource creation succeeded"); + } catch (Resource.CreateFailException e) { + creationFailuresDetected++; + checkCreateFailureId(e.resourceId(), createFailureId); + checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap); + } catch (Resource.CloseFailException e) { + throw new AssertionError("Secondary exception suppression failed:" + e); + } + checkForSingleCreationFailure(creationFailuresDetected); + checkClosedList(closedList, createFailureId); + } + } + } + + public static void testCreateFailure3Nested() { + for (int createFailureId = 0; createFailureId < 3; createFailureId++) { + for (int bitMap = 0, n = 1 << createFailureId; bitMap < n; bitMap++) { + int creationFailuresDetected = 0; + List closedList = new ArrayList(); + try (Resource r0 = createResource(0, createFailureId, bitMap, closedList)) { + try (Resource r1 = createResource(1, createFailureId, bitMap, closedList)) { + try (Resource r2 = createResource(2, createFailureId, bitMap, closedList)) { + throw new AssertionError("Entire resource creation succeeded"); + } + } + } catch (Resource.CreateFailException e) { + creationFailuresDetected++; + checkCreateFailureId(e.resourceId(), createFailureId); + checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap); + } catch (Resource.CloseFailException e) { + throw new AssertionError("Secondary exception suppression failed:" + e); + } + checkForSingleCreationFailure(creationFailuresDetected); + checkClosedList(closedList, createFailureId); + } + } + } + + public static void testCreateFailure4() { + for (int createFailureId = 0; createFailureId < 4; createFailureId++) { + for (int bitMap = 0, n = 1 << createFailureId; bitMap < n; bitMap++) { + int creationFailuresDetected = 0; + List closedList = new ArrayList(); + try (Resource r0 = createResource(0, createFailureId, bitMap, closedList); + Resource r1 = createResource(1, createFailureId, bitMap, closedList); + Resource r2 = createResource(2, createFailureId, bitMap, closedList); + Resource r3 = createResource(3, createFailureId, bitMap, closedList)) { + throw new AssertionError("Entire resource creation succeeded"); + } catch (Resource.CreateFailException e) { + creationFailuresDetected++; + checkCreateFailureId(e.resourceId(), createFailureId); + checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap); + } catch (Resource.CloseFailException e) { + throw new AssertionError("Secondary exception suppression failed:" + e); + } + checkForSingleCreationFailure(creationFailuresDetected); + checkClosedList(closedList, createFailureId); + } + } + } + + public static void testCreateFailure4Nested() { + for (int createFailureId = 0; createFailureId < 4; createFailureId++) { + for (int bitMap = 0, n = 1 << createFailureId; bitMap < n; bitMap++) { + int creationFailuresDetected = 0; + List closedList = new ArrayList(); + try (Resource r0 = createResource(0, createFailureId, bitMap, closedList)) { + try (Resource r1 = createResource(1, createFailureId, bitMap, closedList)) { + try (Resource r2 = createResource(2, createFailureId, bitMap, closedList)) { + try (Resource r3 = createResource(3, createFailureId, bitMap, closedList)) { + throw new AssertionError("Entire resource creation succeeded"); + } + } + } + } catch (Resource.CreateFailException e) { + creationFailuresDetected++; + checkCreateFailureId(e.resourceId(), createFailureId); + checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap); + } catch (Resource.CloseFailException e) { + throw new AssertionError("Secondary exception suppression failed:" + e); + } + checkForSingleCreationFailure(creationFailuresDetected); + checkClosedList(closedList, createFailureId); + } + } + } + + public static void testCreateFailure5() { + for (int createFailureId = 0; createFailureId < 5; createFailureId++) { + for (int bitMap = 0, n = 1 << createFailureId; bitMap < n; bitMap++) { + int creationFailuresDetected = 0; + List closedList = new ArrayList(); + try (Resource r0 = createResource(0, createFailureId, bitMap, closedList); + Resource r1 = createResource(1, createFailureId, bitMap, closedList); + Resource r2 = createResource(2, createFailureId, bitMap, closedList); + Resource r3 = createResource(3, createFailureId, bitMap, closedList); + Resource r4 = createResource(4, createFailureId, bitMap, closedList)) { + throw new AssertionError("Entire resource creation succeeded"); + } catch (Resource.CreateFailException e) { + creationFailuresDetected++; + checkCreateFailureId(e.resourceId(), createFailureId); + checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap); + } catch (Resource.CloseFailException e) { + throw new AssertionError("Secondary exception suppression failed:" + e); + } + checkForSingleCreationFailure(creationFailuresDetected); + checkClosedList(closedList, createFailureId); + } + } + } + + public static void testCreateFailure5Nested() { + for (int createFailureId = 0; createFailureId < 5; createFailureId++) { + for (int bitMap = 0, n = 1 << createFailureId; bitMap < n; bitMap++) { + int creationFailuresDetected = 0; + List closedList = new ArrayList(); + try (Resource r0 = createResource(0, createFailureId, bitMap, closedList)) { + try (Resource r1 = createResource(1, createFailureId, bitMap, closedList)) { + try (Resource r2 = createResource(2, createFailureId, bitMap, closedList)) { + try (Resource r3 = createResource(3, createFailureId, bitMap, closedList)) { + try (Resource r4 = createResource(4, createFailureId, bitMap, closedList)) { + throw new AssertionError("Entire resource creation succeeded"); + } + } + } + } + } catch (Resource.CreateFailException e) { + creationFailuresDetected++; + checkCreateFailureId(e.resourceId(), createFailureId); + checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap); + } catch (Resource.CloseFailException e) { + throw new AssertionError("Secondary exception suppression failed:" + e); + } + checkForSingleCreationFailure(creationFailuresDetected); + checkClosedList(closedList, createFailureId); + } + } + } + + /** + * Create a resource with the specified ID. The ID must be less than createFailureId. + * A subsequent attempt to close the resource will fail iff the corresponding bit + * is set in closeFailureBitMap. When an attempt is made to close this resource, + * its ID will be added to closedList, regardless of whether the attempt succeeds. + * + * @param id the ID of this resource + * @param createFailureId the ID of the resource whose creation will fail + * @param closeFailureBitMap a bit vector describing which resources should throw an + * exception when close is attempted + * @param closedList a list on which to record resource close attempts + * @throws AssertionError if no attempt should be made to create this resource + */ + private static Resource createResource(int id, + int createFailureId, + int closeFailureBitMap, + List closedList) throws Resource.CreateFailException { + if (id > createFailureId) + throw new AssertionError("Resource " + id + " shouldn't be created"); + boolean createSucceeds = id != createFailureId; + boolean closeSucceeds = (closeFailureBitMap & (1 << id)) == 0; + return new Resource(id, createSucceeds, closeSucceeds, closedList); + } + + + /** + * Check that an observed creation failure has the expected resource ID. + * + * @param foundId the ID of the resource whose creation failed + * @param expectedId the ID of the resource whose creation should have failed + */ + private static void checkCreateFailureId(int foundId, int expectedId) { + if (foundId != expectedId) + throw new AssertionError("Wrong resource creation failed. Found ID " + + foundId + " expected " + expectedId); + } + + /** + * Check for proper suppressed exceptions in proper order. + * + * @param suppressedExceptions the suppressed exceptions array returned by + * getSuppressedExceptions() + * @bitmap a bitmap indicating which suppressed exceptions are expected. + * Bit i is set iff id should throw a CloseFailException. + */ + private static void checkSuppressedExceptions(Throwable[] suppressedExceptions, int bitMap) { + if (suppressedExceptions.length != Integer.bitCount(bitMap)) + throw new AssertionError("Expected " + Integer.bitCount(bitMap) + + " suppressed exceptions, got " + suppressedExceptions.length); + + int prevCloseFailExceptionId = Integer.MAX_VALUE; + for (Throwable t : suppressedExceptions) { + int id = ((Resource.CloseFailException) t).resourceId(); + if ((1 << id & bitMap) == 0) + throw new AssertionError("Unexpected suppressed CloseFailException: " + id); + if (id > prevCloseFailExceptionId) + throw new AssertionError("Suppressed CloseFailException" + id + + " followed " + prevCloseFailExceptionId); + } + } + + /** + * Check that exactly one resource creation failed. + * + * @param numCreationFailuresDetected the number of creation failures detected + */ + private static void checkForSingleCreationFailure(int numCreationFailuresDetected) { + if (numCreationFailuresDetected != 1) + throw new AssertionError("Wrong number of creation failures: " + + numCreationFailuresDetected); + } + + /** + * Check that a close was attempted on every resourced that was successfully opened, + * and that the close attempts occurred in the proper order. + * + * @param closedList the resource IDs of the close attempts, in the order they occurred + * @param the ID of the resource whose creation failed. Close attempts should occur + * for all previous resources, in reverse order. + */ + private static void checkClosedList(List closedList, int createFailureId) { + List expectedList = new ArrayList(createFailureId); + for (int i = createFailureId - 1; i >= 0; i--) + expectedList.add(i); + if (!closedList.equals(expectedList)) + throw new AssertionError("Closing sequence " + closedList + " != " + expectedList); + } + + /* + * The following tests simulate the creation of several resources, followed + * by success or failure of forward processing. They test that all resources + * are properly closed, even if one or more of the close attempts fails. + */ + + public static void testCreateSuccess1() { + for (int bitMap = 0, n = 1 << 1; bitMap < n; bitMap++) { + for (int failure = 0; failure < 2; failure++) { + List closedList = new ArrayList(); + try (Resource r0 = createResource(0, bitMap, closedList)) { + if (failure != 0) + throw new MyKindOfException(); + } catch (Resource.CreateFailException e) { + throw new AssertionError( + "Resource creation failed: " + e.resourceId()); + } catch (MyKindOfException e) { + if (failure == 0) + throw new AssertionError("Unexpected MyKindOfException"); + checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap); + } catch (Resource.CloseFailException e) { + if (failure == 1) + throw new AssertionError("Secondary exception suppression failed"); + int id = e.resourceId(); + if (bitMap == 0) + throw new AssertionError("Unexpected CloseFailException: " + id); + int highestCloseFailBit = Integer.highestOneBit(bitMap); + if (1 << id != highestCloseFailBit) { + throw new AssertionError("CloseFailException: got id " + id + + ", expected lg(" + highestCloseFailBit +")"); + } + checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap & ~highestCloseFailBit); + } + checkClosedList(closedList, 1); + } + } + } + + public static void testCreateSuccess2() { + for (int bitMap = 0, n = 1 << 2; bitMap < n; bitMap++) { + for (int failure = 0; failure < 2; failure++) { + List closedList = new ArrayList(); + try (Resource r0 = createResource(0, bitMap, closedList); + Resource r1 = createResource(1, bitMap, closedList)) { + if (failure != 0) + throw new MyKindOfException(); + } catch (Resource.CreateFailException e) { + throw new AssertionError( + "Resource creation failed: " + e.resourceId()); + } catch (MyKindOfException e) { + if (failure == 0) + throw new AssertionError("Unexpected MyKindOfException"); + checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap); + } catch (Resource.CloseFailException e) { + if (failure == 1) + throw new AssertionError("Secondary exception suppression failed"); + int id = e.resourceId(); + if (bitMap == 0) + throw new AssertionError("Unexpected CloseFailException: " + id); + int highestCloseFailBit = Integer.highestOneBit(bitMap); + if (1 << id != highestCloseFailBit) { + throw new AssertionError("CloseFailException: got id " + id + + ", expected lg(" + highestCloseFailBit +")"); + } + checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap & ~highestCloseFailBit); + } + checkClosedList(closedList, 2); + } + } + } + + public static void testCreateSuccess2Nested() { + for (int bitMap = 0, n = 1 << 2; bitMap < n; bitMap++) { + for (int failure = 0; failure < 2; failure++) { + List closedList = new ArrayList(); + try (Resource r0 = createResource(0, bitMap, closedList)) { + try (Resource r1 = createResource(1, bitMap, closedList)) { + if (failure != 0) + throw new MyKindOfException(); + } + } catch (Resource.CreateFailException e) { + throw new AssertionError( + "Resource creation failed: " + e.resourceId()); + } catch (MyKindOfException e) { + if (failure == 0) + throw new AssertionError("Unexpected MyKindOfException"); + checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap); + } catch (Resource.CloseFailException e) { + if (failure == 1) + throw new AssertionError("Secondary exception suppression failed"); + int id = e.resourceId(); + if (bitMap == 0) + throw new AssertionError("Unexpected CloseFailException: " + id); + int highestCloseFailBit = Integer.highestOneBit(bitMap); + if (1 << id != highestCloseFailBit) { + throw new AssertionError("CloseFailException: got id " + id + + ", expected lg(" + highestCloseFailBit +")"); + } + checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap & ~highestCloseFailBit); + } + checkClosedList(closedList, 2); + } + } + } + + public static void testCreateSuccess3() { + for (int bitMap = 0, n = 1 << 3; bitMap < n; bitMap++) { + for (int failure = 0; failure < 2; failure++) { + List closedList = new ArrayList(); + try (Resource r0 = createResource(0, bitMap, closedList); + Resource r1 = createResource(1, bitMap, closedList); + Resource r2 = createResource(2, bitMap, closedList)) { + if (failure != 0) + throw new MyKindOfException(); + } catch (Resource.CreateFailException e) { + throw new AssertionError( + "Resource creation failed: " + e.resourceId()); + } catch (MyKindOfException e) { + if (failure == 0) + throw new AssertionError("Unexpected MyKindOfException"); + checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap); + } catch (Resource.CloseFailException e) { + if (failure == 1) + throw new AssertionError("Secondary exception suppression failed"); + int id = e.resourceId(); + if (bitMap == 0) + throw new AssertionError("Unexpected CloseFailException: " + id); + int highestCloseFailBit = Integer.highestOneBit(bitMap); + if (1 << id != highestCloseFailBit) { + throw new AssertionError("CloseFailException: got id " + id + + ", expected lg(" + highestCloseFailBit +")"); + } + checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap & ~highestCloseFailBit); + } + checkClosedList(closedList, 3); + } + } + } + + public static void testCreateSuccess3Nested() { + for (int bitMap = 0, n = 1 << 3; bitMap < n; bitMap++) { + for (int failure = 0; failure < 2; failure++) { + List closedList = new ArrayList(); + try (Resource r0 = createResource(0, bitMap, closedList)) { + try (Resource r1 = createResource(1, bitMap, closedList)) { + try (Resource r2 = createResource(2, bitMap, closedList)) { + if (failure != 0) + throw new MyKindOfException(); + } + } + } catch (Resource.CreateFailException e) { + throw new AssertionError( + "Resource creation failed: " + e.resourceId()); + } catch (MyKindOfException e) { + if (failure == 0) + throw new AssertionError("Unexpected MyKindOfException"); + checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap); + } catch (Resource.CloseFailException e) { + if (failure == 1) + throw new AssertionError("Secondary exception suppression failed"); + int id = e.resourceId(); + if (bitMap == 0) + throw new AssertionError("Unexpected CloseFailException: " + id); + int highestCloseFailBit = Integer.highestOneBit(bitMap); + if (1 << id != highestCloseFailBit) { + throw new AssertionError("CloseFailException: got id " + id + + ", expected lg(" + highestCloseFailBit +")"); + } + checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap & ~highestCloseFailBit); + } + checkClosedList(closedList, 3); + } + } + } + + public static void testCreateSuccess4() { + for (int bitMap = 0, n = 1 << 4; bitMap < n; bitMap++) { + for (int failure = 0; failure < 2; failure++) { + List closedList = new ArrayList(); + try (Resource r0 = createResource(0, bitMap, closedList); + Resource r1 = createResource(1, bitMap, closedList); + Resource r2 = createResource(2, bitMap, closedList); + Resource r3 = createResource(3, bitMap, closedList)) { + if (failure != 0) + throw new MyKindOfException(); + } catch (Resource.CreateFailException e) { + throw new AssertionError( + "Resource creation failed: " + e.resourceId()); + } catch (MyKindOfException e) { + if (failure == 0) + throw new AssertionError("Unexpected MyKindOfException"); + checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap); + } catch (Resource.CloseFailException e) { + if (failure == 1) + throw new AssertionError("Secondary exception suppression failed"); + int id = e.resourceId(); + if (bitMap == 0) + throw new AssertionError("Unexpected CloseFailException: " + id); + int highestCloseFailBit = Integer.highestOneBit(bitMap); + if (1 << id != highestCloseFailBit) { + throw new AssertionError("CloseFailException: got id " + id + + ", expected lg(" + highestCloseFailBit +")"); + } + checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap & ~highestCloseFailBit); + } + checkClosedList(closedList, 4); + } + } + } + + public static void testCreateSuccess4Nested() { + for (int bitMap = 0, n = 1 << 4; bitMap < n; bitMap++) { + for (int failure = 0; failure < 2; failure++) { + List closedList = new ArrayList(); + try (Resource r0 = createResource(0, bitMap, closedList)) { + try (Resource r1 = createResource(1, bitMap, closedList)) { + try (Resource r2 = createResource(2, bitMap, closedList)) { + try (Resource r3 = createResource(3, bitMap, closedList)) { + if (failure != 0) + throw new MyKindOfException(); + } + } + } + } catch (Resource.CreateFailException e) { + throw new AssertionError( + "Resource creation failed: " + e.resourceId()); + } catch (MyKindOfException e) { + if (failure == 0) + throw new AssertionError("Unexpected MyKindOfException"); + checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap); + } catch (Resource.CloseFailException e) { + if (failure == 1) + throw new AssertionError("Secondary exception suppression failed"); + int id = e.resourceId(); + if (bitMap == 0) + throw new AssertionError("Unexpected CloseFailException: " + id); + int highestCloseFailBit = Integer.highestOneBit(bitMap); + if (1 << id != highestCloseFailBit) { + throw new AssertionError("CloseFailException: got id " + id + + ", expected lg(" + highestCloseFailBit +")"); + } + checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap & ~highestCloseFailBit); + } + checkClosedList(closedList, 4); + } + } + } + + public static void testCreateSuccess5() { + for (int bitMap = 0, n = 1 << 5; bitMap < n; bitMap++) { + for (int failure = 0; failure < 2; failure++) { + List closedList = new ArrayList(); + try (Resource r0 = createResource(0, bitMap, closedList); + Resource r1 = createResource(1, bitMap, closedList); + Resource r2 = createResource(2, bitMap, closedList); + Resource r3 = createResource(3, bitMap, closedList); + Resource r4 = createResource(4, bitMap, closedList)) { + if (failure != 0) + throw new MyKindOfException(); + } catch (Resource.CreateFailException e) { + throw new AssertionError("Resource creation failed: " + e.resourceId()); + } catch (MyKindOfException e) { + if (failure == 0) + throw new AssertionError("Unexpected MyKindOfException"); + checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap); + } catch (Resource.CloseFailException e) { + if (failure == 1) + throw new AssertionError("Secondary exception suppression failed"); + int id = e.resourceId(); + if (bitMap == 0) + throw new AssertionError("Unexpected CloseFailException: " + id); + int highestCloseFailBit = Integer.highestOneBit(bitMap); + if (1 << id != highestCloseFailBit) { + throw new AssertionError("CloseFailException: got id " + id + + ", expected lg(" + highestCloseFailBit +")"); + } + checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap & ~highestCloseFailBit); + } + checkClosedList(closedList, 5); + } + } + } + + public static void testCreateSuccess5Nested() { + for (int bitMap = 0, n = 1 << 5; bitMap < n; bitMap++) { + for (int failure = 0; failure < 2; failure++) { + List closedList = new ArrayList(); + try (Resource r0 = createResource(0, bitMap, closedList)) { + try (Resource r1 = createResource(1, bitMap, closedList)) { + try (Resource r2 = createResource(2, bitMap, closedList)) { + try (Resource r3 = createResource(3, bitMap, closedList)) { + try (Resource r4 = createResource(4, bitMap, closedList)) { + if (failure != 0) + throw new MyKindOfException(); + } + } + } + } + } catch (Resource.CreateFailException e) { + throw new AssertionError("Resource creation failed: " + e.resourceId()); + } catch (MyKindOfException e) { + if (failure == 0) + throw new AssertionError("Unexpected MyKindOfException"); + checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap); + } catch (Resource.CloseFailException e) { + if (failure == 1) + throw new AssertionError("Secondary exception suppression failed"); + int id = e.resourceId(); + if (bitMap == 0) + throw new AssertionError("Unexpected CloseFailException: " + id); + int highestCloseFailBit = Integer.highestOneBit(bitMap); + if (1 << id != highestCloseFailBit) { + throw new AssertionError("CloseFailException: got id " + id + + ", expected lg(" + highestCloseFailBit +")"); + } + checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap & ~highestCloseFailBit); + } + checkClosedList(closedList, 5); + } + } + } + + private static Resource createResource(int id, + int closeFailureBitMap, + List closedList) throws Resource.CreateFailException { + boolean closeSucceeds = (closeFailureBitMap & (1 << id)) == 0; + return new Resource(id, true, closeSucceeds, closedList); + } + + private static class MyKindOfException extends Exception { + } +} + +class Resource implements AutoCloseable { + /** A number identifying this resource */ + private final int resourceId; + + /** Whether the close call on this resource should succeed or fail */ + private final boolean closeSucceeds; + + /** When resource is closed, it records its ID in this list */ + private final List closedList; + + Resource(int resourceId, boolean createSucceeds, boolean closeSucceeds, + List closedList) throws CreateFailException { + if (!createSucceeds) + throw new CreateFailException(resourceId); + this.resourceId = resourceId; + this.closeSucceeds = closeSucceeds; + this.closedList = closedList; + } + + public void close() throws CloseFailException { + closedList.add(resourceId); + if (!closeSucceeds) + throw new CloseFailException(resourceId); + } + + public static class ResourceException extends RuntimeException { + private final int resourceId; + + public ResourceException(int resourceId) { + super("Resource ID = " + resourceId); + this.resourceId = resourceId; + } + + public int resourceId() { + return resourceId; + } + } + + public static class CreateFailException extends ResourceException { + public CreateFailException(int resourceId) { + super(resourceId); + } + } + + public static class CloseFailException extends ResourceException { + public CloseFailException(int resourceId) { + super(resourceId); + } + } +} diff --git a/langtools/test/tools/javac/TryWithResources/WeirdTwr.java b/langtools/test/tools/javac/TryWithResources/WeirdTwr.java new file mode 100644 index 00000000000..7092986ffd3 --- /dev/null +++ b/langtools/test/tools/javac/TryWithResources/WeirdTwr.java @@ -0,0 +1,48 @@ +/* + * 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 6911256 6964740 + * @author Joseph D. Darcy + * @summary Strange TWRs + * @compile/fail -source 6 WeirdTwr.java + * @compile WeirdTwr.java + * @run main WeirdTwr + */ + +public class WeirdTwr implements AutoCloseable { + private static int closeCount = 0; + public static void main(String... args) { + try(WeirdTwr r1 = new WeirdTwr(); WeirdTwr r2 = r1) { + if (r1 != r2) + throw new RuntimeException("Unexpected inequality."); + } + if (closeCount != 2) + throw new RuntimeException("bad closeCount" + closeCount); + } + + public void close() { + closeCount++; + } +} diff --git a/langtools/test/tools/javac/processing/model/element/TestResourceVariable.java b/langtools/test/tools/javac/processing/model/element/TestResourceVariable.java new file mode 100644 index 00000000000..45829b46e33 --- /dev/null +++ b/langtools/test/tools/javac/processing/model/element/TestResourceVariable.java @@ -0,0 +1,113 @@ +/* + * 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 6911256 6964740 + * @summary Test that the resource variable kind is appropriately set + * @author Joseph D. Darcy + * @build TestResourceVariable + * @compile/fail -processor TestResourceVariable -proc:only TestResourceVariable.java + */ + +// Bug should be filed for this misbehavior + +import java.io.*; +import javax.annotation.processing.*; +import javax.lang.model.*; +import javax.lang.model.element.*; +import javax.lang.model.type.*; +import javax.lang.model.util.*; +import java.util.*; +import com.sun.source.tree.*; +import com.sun.source.util.*; +import static javax.tools.Diagnostic.Kind.*; + +/** + * Using the tree API, retrieve element representations of the + * resource of an ARM block and verify their kind tags are set + * appropriately. + */ +@SupportedAnnotationTypes("*") +public class TestResourceVariable extends AbstractProcessor implements AutoCloseable { + int resourceVariableCount = 0; + + public boolean process(Set annotations, + RoundEnvironment roundEnv) { + if (!roundEnv.processingOver()) { + Trees trees = Trees.instance(processingEnv); + + for(Element rootElement : roundEnv.getRootElements()) { + TreePath treePath = trees.getPath(rootElement); + + (new ResourceVariableScanner(trees)). + scan(trees.getTree(rootElement), + treePath.getCompilationUnit()); + } + if (resourceVariableCount != 3) + throw new RuntimeException("Bad resource variable count " + + resourceVariableCount); + } + return true; + } + + @Override + public void close() {} + + private void test1() { + try(TestResourceVariable trv = this) {} + } + + private void test2() { + try(TestResourceVariable trv1 = this; TestResourceVariable trv2 = trv1) {} + } + + class ResourceVariableScanner extends TreeScanner { + private Trees trees; + + public ResourceVariableScanner(Trees trees) { + super(); + this.trees = trees; + } + @Override + public Void visitVariable(VariableTree node, CompilationUnitTree cu) { + Element element = trees.getElement(trees.getPath(cu, node)); + if (element == null) { + System.out.println("Null variable element: " + node); + } else { + System.out.println("Name: " + element.getSimpleName() + + "\tKind: " + element.getKind()); + } + if (element != null && + element.getKind() == ElementKind.RESOURCE_VARIABLE) { + resourceVariableCount++; + } + return super.visitVariable(node, cu); + } + } + + @Override + public SourceVersion getSupportedSourceVersion() { + return SourceVersion.latest(); + } +} From daf491a814c75a35085a2f55915daac25c6438a3 Mon Sep 17 00:00:00 2001 From: John Coomes Date: Fri, 16 Jul 2010 21:33:21 -0700 Subject: [PATCH 017/110] 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 018/110] 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 019/110] 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 020/110] 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 021/110] 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 3888d500b934ccece8ffec99f8e9efcd4a8389dd Mon Sep 17 00:00:00 2001 From: Andrei Pangin Date: Tue, 20 Jul 2010 08:41:42 -0700 Subject: [PATCH 022/110] 6964170: Verifier crashes Check if klassOop != NULL rather than klass_part != NULL Reviewed-by: kamg, never --- hotspot/src/share/vm/classfile/verificationType.cpp | 6 ++++-- hotspot/src/share/vm/classfile/verifier.cpp | 8 ++------ 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/hotspot/src/share/vm/classfile/verificationType.cpp b/hotspot/src/share/vm/classfile/verificationType.cpp index ebb5ac85f16..7b507efa901 100644 --- a/hotspot/src/share/vm/classfile/verificationType.cpp +++ b/hotspot/src/share/vm/classfile/verificationType.cpp @@ -70,7 +70,9 @@ bool VerificationType::is_reference_assignable_from( } else if (is_array() && from.is_array()) { VerificationType comp_this = get_component(CHECK_false); VerificationType comp_from = from.get_component(CHECK_false); - return comp_this.is_assignable_from(comp_from, context, CHECK_false); + if (!comp_this.is_bogus() && !comp_from.is_bogus()) { + return comp_this.is_assignable_from(comp_from, context, CHECK_false); + } } return false; } @@ -98,7 +100,7 @@ VerificationType VerificationType::get_component(TRAPS) const { CHECK_(VerificationType::bogus_type())); return VerificationType::reference_type(component); default: - ShouldNotReachHere(); + // Met an invalid type signature, e.g. [X return VerificationType::bogus_type(); } } diff --git a/hotspot/src/share/vm/classfile/verifier.cpp b/hotspot/src/share/vm/classfile/verifier.cpp index 603d4ec3c25..1df514dc1c4 100644 --- a/hotspot/src/share/vm/classfile/verifier.cpp +++ b/hotspot/src/share/vm/classfile/verifier.cpp @@ -1847,12 +1847,8 @@ void ClassVerifier::verify_invoke_init( if (type == VerificationType::uninitialized_this_type()) { // The method must be an method of either this class, or one of its // superclasses - klassOop oop = current_class()(); - Klass* klass = oop->klass_part(); - while (klass != NULL && ref_class_type.name() != klass->name()) { - klass = klass->super()->klass_part(); - } - if (klass == NULL) { + if (ref_class_type.name() != current_class()->name() && + !name_in_supers(ref_class_type.name(), current_class())) { verify_error(bci, "Bad method call"); return; } From 2890d62dbbe0435362d579b12669acdebc763724 Mon Sep 17 00:00:00 2001 From: Chris Hegarty Date: Wed, 21 Jul 2010 13:29:26 +0100 Subject: [PATCH 023/110] 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 024/110] 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 025/110] 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 026/110] 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 027/110] 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 028/110] 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 7eb8c115ec13d9499917b3cdae2a32519981417e Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Thu, 22 Jul 2010 11:02:54 -0700 Subject: [PATCH 029/110] 6968063: provide examples of code that generate diagnostics Reviewed-by: mcimadamore --- langtools/make/build.xml | 29 + .../test/tools/javac/diags/CheckExamples.java | 218 +++++++ langtools/test/tools/javac/diags/Example.java | 523 ++++++++++++++++ .../test/tools/javac/diags/FileManager.java | 191 ++++++ .../test/tools/javac/diags/HTMLWriter.java | 582 ++++++++++++++++++ .../tools/javac/diags/README.examples.txt | 134 ++++ .../test/tools/javac/diags/RunExamples.java | 582 ++++++++++++++++++ .../tools/javac/diags/examples.not-yet.txt | 115 ++++ .../examples/AbstractCantBeAccessed.java | 34 + .../examples/AbstractCantBeInstantiated.java | 32 + .../examples/AbstractMethodCantHaveBody.java | 28 + .../javac/diags/examples/AlreadyDefined.java | 29 + .../diags/examples/AlreadyDefinedImport.java | 29 + .../AlreadDefinedStaticImport.java | 27 + .../AlreadyDefinedStaticImport/p/E1.java | 26 + .../AlreadyDefinedStaticImport/p/E2.java | 26 + .../diags/examples/AnnoNotApplicable.java | 33 + .../diags/examples/AnnoNotValidForType.java | 31 + .../examples/AnnoValueMustBeAnnotation.java | 35 ++ .../examples/AnnoValueMustBeClassLiteral.java | 31 + .../AnnosWithoutProcessors.java | 30 + .../processors/AnnoProc.java | 38 ++ .../examples/AnnotationMissingValue.java | 31 + .../examples/AnnotationMustBeNameValue.java | 32 + .../examples/AnnotationsNotSupported.java | 28 + .../AnonClassImplInterfaceNoArgs.java | 30 + .../AnonClassImplInterfaceNoQualForNew.java | 31 + .../AnonClassImplInterfaceNoTypeArgs.java | 30 + .../javac/diags/examples/AnonymousClass.java | 33 + .../javac/diags/examples/ArrayAndVarargs.java | 29 + .../javac/diags/examples/ArrayDimMissing.java | 28 + .../javac/diags/examples/ArrayRequired.java | 29 + .../diags/examples/AssertAsIdentifier.java | 29 + .../diags/examples/AssertAsIdentifier2.java | 28 + .../diags/examples/AttrMustBeConstant.java | 31 + .../BadSourceFileHeader.java | 30 + .../BadSourceFileHeader/sourcepath/p/A.java | 28 + .../examples/BreakOutsideSwitchLoop.java | 30 + .../javac/diags/examples/CallMustBeFirst.java | 31 + .../CannotCreateArrayWithTypeArgs.java | 28 + .../diags/examples/CantApplyDiamond.java | 34 + .../diags/examples/CantAssignToFinal.java | 32 + .../tools/javac/diags/examples/CantDeref.java | 30 + .../diags/examples/CantExtendIntfAnno.java | 28 + .../javac/diags/examples/CantImplement.java | 33 + .../diags/examples/CantInheritDiffArg.java | 28 + .../diags/examples/CantRefBeforeConstr.java | 36 ++ .../javac/diags/examples/CantResolve.java | 31 + .../javac/diags/examples/CantResolveArgs.java | 35 ++ .../diags/examples/CantResolveArgsParams.java | 31 + .../diags/examples/CantResolveLocation.java | 28 + .../examples/CantResolveLocationArgs.java | 30 + .../CantResolveLocationArgsParams.java | 32 + .../examples/CantReturnValueForVoid.java | 30 + .../javac/diags/examples/CatchWithoutTry.java | 33 + .../javac/diags/examples/ClashesWith.java | 33 + .../javac/diags/examples/ClassCantWrite.java | 27 + .../diags/examples/ClassPublicInFile.java | 26 + .../examples/ConcreteInheritanceConflict.java | 31 + .../diags/examples/ConstExprRequired.java | 36 ++ .../javac/diags/examples/ConstantSVUID.java | 31 + .../diags/examples/ContinueOutsideLoop.java | 30 + .../javac/diags/examples/CountError.java | 30 + .../diags/examples/CountErrorPlural.java | 31 + .../tools/javac/diags/examples/CountWarn.java | 35 ++ .../javac/diags/examples/CountWarnPlural.java | 36 ++ .../diags/examples/CyclicAnnoElement.java | 28 + .../diags/examples/CyclicInheritance.java | 26 + .../DefaultAllowedInIntfAnnotationMember.java | 28 + .../diags/examples/DeprecatedFilename.java | 32 + .../DeprecatedFilenameAdditional.java | 37 ++ .../DeprecatedPlural/DeprecatedClass.java | 25 + .../DeprecatedPlural/DeprecatedFilename.java | 26 + .../DeprecatedPlural/DeprecatedPlural.java | 29 + .../DeprecatedClass.java | 25 + .../DeprecatedFilename.java | 26 + .../DeprecatedPlural.java | 26 + .../DeprecatedPluralAdditional.java | 30 + .../diags/examples/DiamondInvalidArg.java | 31 + .../diags/examples/DiamondInvalidArgs.java | 32 + .../diags/examples/DiamondNotSupported.java | 33 + .../examples/DirPathElementNotFound.java | 28 + .../tools/javac/diags/examples/DivZero.java | 31 + .../javac/diags/examples/DoesNotOverride.java | 30 + .../javac/diags/examples/DoesntExist.java | 26 + .../diags/examples/DotClassExpected.java | 28 + .../diags/examples/DuplicateAnnotation.java | 30 + .../DuplicateAnnotationMemberValue.java | 31 + .../diags/examples/DuplicateCaseLabel.java | 34 + .../javac/diags/examples/DuplicateClass.java | 28 + .../diags/examples/DuplicateDefaultLabel.java | 35 ++ .../javac/diags/examples/ElseWithoutIf.java | 31 + .../diags/examples/EmptyBytecodeIdent.java | 28 + .../diags/examples/EmptyCharLiteral.java | 31 + .../tools/javac/diags/examples/EmptyIf.java | 31 + .../diags/examples/EnclClassRequired.java | 30 + .../EnumAnnoValueMustBeEnumConst.java | 33 + .../diags/examples/EnumAsIdentifier.java | 29 + .../diags/examples/EnumAsIdentifier2.java | 28 + .../examples/EnumCantBeInstantiated.java | 30 + .../diags/examples/EnumConstRequired.java | 35 ++ .../diags/examples/EnumLabelUnqualified.java | 36 ++ .../javac/diags/examples/EnumNoFinalize.java | 32 + .../diags/examples/EnumNoSubclassing.java | 26 + .../examples/EnumTypesNotExtensible.java | 29 + .../diags/examples/EnumsMustBeStatic.java | 30 + .../diags/examples/EnumsNotSupported.java | 27 + .../ErrProcMessager/ErrProcMessager.java | 27 + .../ErrProcMessager/processors/AnnoProc.java | 43 ++ .../examples/ErrSyntheticNameConflict.java | 33 + .../tools/javac/diags/examples/Error.java | 40 ++ .../diags/examples/ErrorReadingFile.java | 27 + .../diags/examples/ExceptAlreadyCaught.java | 36 ++ .../diags/examples/ExceptNeverThrown.java | 35 ++ .../tools/javac/diags/examples/Expected2.java | 27 + .../tools/javac/diags/examples/Expected3.java | 26 + .../examples/FinalParamCantBeAssigned.java | 30 + .../diags/examples/FinallyCannotComplete.java | 34 + .../diags/examples/FinallyWithoutTry.java | 31 + .../diags/examples/FloatNumberTooLarge.java | 28 + .../diags/examples/FloatNumberTooSmall.java | 28 + .../diags/examples/ForeachNotApplicable.java | 32 + .../diags/examples/ForeachNotSupported.java | 33 + .../diags/examples/GenericArrayCreation.java | 30 + .../diags/examples/GenericThrowable.java | 26 + .../diags/examples/GenericsNotSupported.java | 27 + .../diags/examples/HasBeenDeprecated.java | 34 + .../diags/examples/IdentifierExpected.java | 32 + .../examples/IllegalBytecodeIdentChar.java | 28 + .../javac/diags/examples/IllegalChar.java | 28 + .../diags/examples/IllegalComboModifiers.java | 28 + .../diags/examples/IllegalEnumStaticRef.java | 29 + .../diags/examples/IllegalEscapeChar.java | 28 + .../diags/examples/IllegalForwardRef.java | 29 + .../diags/examples/IllegalInitializer.java | 28 + .../examples/IllegalLineEndInCharLit.java | 29 + .../diags/examples/IllegalNonAsciiDigit.java | 28 + .../diags/examples/IllegalQualNotIcls.java | 31 + .../javac/diags/examples/IllegalSelfRef.java | 28 + .../diags/examples/IllegalStartOfExpr.java | 28 + .../diags/examples/IllegalUnderscore.java | 28 + .../diags/examples/IllegalUnicodeEscape.java | 28 + .../ImportRequiresCanonical.java | 28 + .../ImportRequiresCanonical/p/Base.java | 28 + .../p/ExtendsBase.java | 27 + .../javac/diags/examples/ImproperSVUID.java | 31 + .../examples/ImproperTypeInnerRawParam.java | 34 + .../examples/ImproperTypeParamMissing.java | 34 + .../diags/examples/IncomparableTypes.java | 28 + .../diags/examples/IncompatibleTypes1.java | 34 + .../diags/examples/InconvertibleTypes.java | 35 ++ .../diags/examples/InexactVarargsCall.java | 35 ++ .../InferredDoNotConformToBounds.java | 35 ++ .../diags/examples/InheritFromFinal.java | 28 + .../examples/InitializerMustComplete.java | 30 + .../examples/InnerClassCantHaveStatic.java | 30 + .../diags/examples/IntNumberTooLarge.java | 28 + .../diags/examples/InterfaceExpected.java | 26 + .../diags/examples/InterfaceNotAllowed.java | 30 + .../IntfAnnotationCantHaveTypeParams.java | 26 + .../examples/IntfAnnotationMemberClash.java | 28 + .../IntfAnnotationsCantHaveParams.java | 28 + .../IntfAnnotationsCantHaveTypeParams.java | 28 + .../examples/IntfMethodCantHaveBody.java | 28 + .../diags/examples/InvalidAnnoMemberType.java | 28 + .../diags/examples/InvalidBinaryNumber.java | 31 + .../diags/examples/InvalidHexNumber.java | 29 + .../diags/examples/InvalidInferredTypes.java | 38 ++ .../diags/examples/InvalidInstanceof.java | 31 + .../diags/examples/InvalidMethodDecl.java | 28 + .../javac/diags/examples/KindnameClass.java | 31 + .../diags/examples/KindnameConstructor.java | 38 ++ .../javac/diags/examples/KindnameMethod.java | 32 + .../diags/examples/KindnameVariable.java | 32 + .../javac/diags/examples/LabelInUse.java | 37 ++ .../tools/javac/diags/examples/LocalEnum.java | 30 + .../diags/examples/LocalVarNeedsFinal.java | 35 ++ .../tools/javac/diags/examples/LongSVUID.java | 31 + .../javac/diags/examples/MalformedFpLit.java | 29 + .../MalformedSupported.java | 27 + .../processors/AnnoProc.java | 38 ++ .../diags/examples/MethodDoesNotOverride.java | 29 + .../diags/examples/MightBeAssignedInLoop.java | 33 + .../examples/MissingDeprecatedAnnotation.java | 29 + .../diags/examples/MissingMethodBody.java | 28 + .../examples/MissingReturnStatement.java | 29 + .../diags/examples/MissingReturnValue.java | 30 + .../javac/diags/examples/MissingSVUID.java | 30 + .../diags/examples/ModifierNotAllowed.java | 26 + .../examples/MulticatchCantBeAssigned.java | 38 ++ .../diags/examples/MulticatchMustBeFinal.java | 38 ++ .../examples/MulticatchNotSupported.java | 42 ++ .../diags/examples/NameClashSameErasure.java | 31 + .../NameClashSameErasureNoOverride.java | 34 + .../examples/NativeMethodCantHaveBody.java | 28 + .../examples/NeitherConditionalSubtype.java | 31 + .../diags/examples/NewNotAllowedInAnno.java | 31 + .../tools/javac/diags/examples/NoArgs.java | 32 + .../examples/NoExplicitAnnoProcRequested.java | 28 + .../diags/examples/NoInterfaceExpected.java | 26 + .../javac/diags/examples/NoInterfaceHere.java | 28 + .../javac/diags/examples/NoJavaLang.java | 28 + .../javac/diags/examples/NoSuperclass.java | 32 + .../diags/examples/NonStaticCantBeRef.java | 32 + .../NotDefAccessClassIntfCantAccess.java | 33 + .../NotDefAccessClassIntfCantAccess/p/C.java | 30 + .../NotDefPublicCantAccess.java | 28 + .../examples/NotDefPublicCantAccess/p/C.java | 26 + .../javac/diags/examples/NotEnclClass.java | 28 + .../javac/diags/examples/NotLoopLabel.java | 38 ++ .../javac/diags/examples/NotWithinBounds.java | 31 + .../test/tools/javac/diags/examples/Note.java | 33 + .../NoteProcMessager/NoteProcMessager.java | 27 + .../NoteProcMessager/processors/AnnoProc.java | 43 ++ .../diags/examples/OperatorCantBeApplied.java | 28 + .../tools/javac/diags/examples/Orphaned.java | 31 + .../diags/examples/OverrideDoesntThrow.java | 34 + .../examples/OverrideIncompatibleReturn.java | 38 ++ .../javac/diags/examples/OverrideMeth.java | 33 + .../javac/diags/examples/OverrideStatic.java | 33 + .../examples/OverrideUncheckedReturn.java | 36 ++ .../examples/OverrideUncheckedThrown.java | 34 + .../diags/examples/OverrideVarargsExtra.java | 34 + .../examples/OverrideVarargsMissing.java | 34 + .../diags/examples/OverrideWeakerAccess.java | 29 + .../javac/diags/examples/PackageAnnos.java | 29 + .../p/package-info.java | 24 + .../PackageInfoAlreadySeen/package-info.java | 26 + .../diags/examples/PathElementNotFound.java | 28 + .../diags/examples/PkgClashWithClass/p/q.java | 31 + .../examples/PkgClashWithClass/p/q/C.java | 26 + .../diags/examples/PossibleFallThrough.java | 37 ++ .../diags/examples/PossibleLossPrecision.java | 30 + .../javac/diags/examples/PrematureEOF.java | 26 + .../PrintProcessorInfo.java | 28 + .../processors/AnnoProc.java | 38 ++ .../examples/PrintRounds/PrintRounds.java | 28 + .../PrintRounds/processors/AnnoProc.java | 38 ++ .../ProcCantFindClass/ProcCantFindClass.java | 26 + .../processors/AnnoProc.java | 32 + .../ProcFileReopening/ProcFileReopening.java | 28 + .../processors/AnnoProc.java | 57 ++ .../ProcIllegalFileName.java | 28 + .../processors/AnnoProc.java | 55 ++ .../ProcIncompatibleSourceVersion.java | 27 + .../processors/AnnoProc.java | 35 ++ .../javac/diags/examples/ProcOnlyNoProcs.java | 25 + .../ProcPackageDoesNotExist.java | 26 + .../processors/AnnoProc.java | 39 ++ .../ProcTypeRecreate/ProcTypeRecreate.java | 28 + .../ProcTypeRecreate/processors/AnnoProc.java | 55 ++ .../ProcUnclosedTypeFiles.java | 27 + .../processors/AnnoProc.java | 55 ++ .../ProcUseImplicit/ProcUseImplicit.java | 30 + .../ProcUseImplicit/processors/AnnoProc.java | 54 ++ .../sourcepath/p/SomeClass.java | 26 + .../ProcUseProcOrImplicit.java | 30 + .../processors/AnnoProc.java | 54 ++ .../sourcepath/p/SomeClass.java | 26 + .../ProcessorCantInstantiate.java | 27 + .../processors/AnnoProc.java | 38 ++ .../diags/examples/ProcessorNotFound.java | 27 + .../ProcessorWrongType.java | 27 + .../processors/AnnoProc.java | 24 + .../examples/QualifiedNewStaticClass.java | 30 + .../javac/diags/examples/RawClassUse.java | 31 + .../examples/RecursiveConstrInvocation.java | 30 + .../javac/diags/examples/RedundantCast.java | 29 + .../javac/diags/examples/RefAmbiguous.java | 33 + .../examples/RepeatedAnnotationTarget.java | 29 + .../diags/examples/RepeatedInterface.java | 30 + .../diags/examples/RepeatedModifier.java | 28 + .../javac/diags/examples/ReportAccess.java | 32 + .../javac/diags/examples/ResourceClosed.java | 35 ++ .../examples/ResourceMayNotBeAssigned.java | 34 + .../examples/ResourceNotApplicableToType.java | 32 + .../diags/examples/ResourceNotReferenced.java | 34 + .../diags/examples/ReturnOutsideMethod.java | 28 + .../examples/StaticImportNotSupported.java | 29 + .../Other.java | 28 + .../StaticImportOnlyClassesAndInterfaces.java | 29 + .../examples/StaticNotQualifiedByType.java | 35 ++ .../diags/examples/StringConstRequired.java | 36 ++ .../examples/StringSwitchNotSupported.java | 35 ++ .../javac/diags/examples/SunApiFilename.java | 30 + .../examples/SunApiFilenameAdditional.java | 31 + .../examples/SunApiPlural/SunApiFilename.java | 26 + .../examples/SunApiPlural/SunApiPlural.java | 30 + .../SunApiFilename.java | 26 + .../SunApiPluralAdditional/SunApiPlural.java | 26 + .../SunApiPluralAdditional.java | 30 + .../javac/diags/examples/SunProprietary.java | 28 + .../diags/examples/SuperNotAllowedInEnum.java | 33 + .../examples/ThrowsNotAllowedInAnno.java | 28 + .../examples/TryResourceNotSupported.java | 35 ++ .../examples/TryWithoutCatchOrFinally.java | 32 + .../TryWithoutCatchOrFinallyOrResource.java | 31 + .../examples/TypeAnnotationsNotSupported.java | 33 + .../diags/examples/TypeFoundRequired.java | 32 + .../javac/diags/examples/TypeNoParams.java | 28 + .../diags/examples/TypeReqClassArray.java | 31 + .../javac/diags/examples/TypeReqRef.java | 30 + .../diags/examples/TypeVarCantBeDeref.java | 28 + .../TypeVarMayNotBeFollowedByOtherBounds.java | 28 + .../diags/examples/TypesIncompatible.java | 34 + .../javac/diags/examples/UncheckedAssign.java | 34 + .../diags/examples/UncheckedAssignToVar.java | 36 ++ .../javac/diags/examples/UncheckedCall.java | 34 + .../javac/diags/examples/UncheckedCast.java | 34 + .../javac/diags/examples/UncheckedClash.java | 36 ++ .../diags/examples/UncheckedFilename.java | 31 + .../examples/UncheckedFilenameAdditional.java | 37 ++ .../UncheckedGenericArrayCreation.java | 37 ++ .../diags/examples/UncheckedImplement.java | 36 ++ .../examples/UncheckedMethodInvocation.java | 37 ++ .../UncheckedPlural/UncheckedFilename.java | 28 + .../UncheckedPlural/UncheckedPlural.java | 31 + .../UncheckedFilename1.java | 28 + .../UncheckedFilename2.java | 28 + .../UncheckedPluralAdditional.java | 33 + .../diags/examples/UnclosedBytecodeIdent.java | 28 + .../diags/examples/UnclosedCharLiteral.java | 28 + .../javac/diags/examples/UnclosedComment.java | 30 + .../diags/examples/UnclosedStringLiteral.java | 28 + .../javac/diags/examples/UndefinedLabel.java | 35 ++ .../diags/examples/UndeterminedType1.java | 34 + .../UnmatchedProcessorOptions.java | 27 + .../processors/AnnoProc.java | 39 ++ .../javac/diags/examples/UnnamedPackage.java | 32 + .../diags/examples/UnreachableStatement.java | 31 + .../diags/examples/UnreportedException.java | 30 + ...UnreportedExceptionDefaultConstructor.java | 30 + .../examples/UnsupportedBinaryLiteral.java | 29 + .../diags/examples/UnsupportedEncoding.java | 27 + .../diags/examples/UnsupportedFpLit.java | 29 + .../UnsupportedUnderscoreLiteral.java | 29 + .../examples/VarMightAlreadyBeAssigned.java | 33 + .../VarMightNotHaveBeenInitialized.java | 32 + .../javac/diags/examples/VarargsClash.java | 34 + .../javac/diags/examples/VarargsFilename.java | 29 + .../examples/VarargsFilenameAdditional.java | 31 + .../diags/examples/VarargsImplement.java | 34 + .../examples/VarargsNonReifiableType.java | 32 + .../diags/examples/VarargsNotSupported.java | 29 + .../javac/diags/examples/VarargsOverride.java | 34 + .../VarargsPlural/VarargsFilename.java | 26 + .../examples/VarargsPlural/VarargsPlural.java | 29 + .../VarargsFilename.java | 26 + .../VarargsPlural.java | 26 + .../VarargsPluralAdditional.java | 30 + .../tools/javac/diags/examples/Verbose.java | 35 ++ .../javac/diags/examples/VoidNotAllowed.java | 32 + .../javac/diags/examples/WarnForwardRef.java | 30 + .../WarnProcMessager/WarnProcMessager.java | 27 + .../WarnProcMessager/processors/AnnoProc.java | 43 ++ .../javac/diags/examples/WarnSelfRef.java | 29 + .../examples/WarnSyntheticNameConflict.java | 34 + .../diags/examples/WarningAndWerror.java | 32 + .../javac/diags/examples/WhereCaptured.java | 41 ++ .../javac/diags/examples/WhereCaptured1.java | 42 ++ .../diags/examples/WhereIntersection.java | 43 ++ .../javac/diags/examples/WhereTypeVar.java | 36 ++ .../diags/examples/WrongNumberTypeArgs.java | 30 + 363 files changed, 13449 insertions(+) create mode 100644 langtools/test/tools/javac/diags/CheckExamples.java create mode 100644 langtools/test/tools/javac/diags/Example.java create mode 100644 langtools/test/tools/javac/diags/FileManager.java create mode 100644 langtools/test/tools/javac/diags/HTMLWriter.java create mode 100644 langtools/test/tools/javac/diags/README.examples.txt create mode 100644 langtools/test/tools/javac/diags/RunExamples.java create mode 100644 langtools/test/tools/javac/diags/examples.not-yet.txt create mode 100644 langtools/test/tools/javac/diags/examples/AbstractCantBeAccessed.java create mode 100644 langtools/test/tools/javac/diags/examples/AbstractCantBeInstantiated.java create mode 100644 langtools/test/tools/javac/diags/examples/AbstractMethodCantHaveBody.java create mode 100644 langtools/test/tools/javac/diags/examples/AlreadyDefined.java create mode 100644 langtools/test/tools/javac/diags/examples/AlreadyDefinedImport.java create mode 100644 langtools/test/tools/javac/diags/examples/AlreadyDefinedStaticImport/AlreadDefinedStaticImport.java create mode 100644 langtools/test/tools/javac/diags/examples/AlreadyDefinedStaticImport/p/E1.java create mode 100644 langtools/test/tools/javac/diags/examples/AlreadyDefinedStaticImport/p/E2.java create mode 100644 langtools/test/tools/javac/diags/examples/AnnoNotApplicable.java create mode 100644 langtools/test/tools/javac/diags/examples/AnnoNotValidForType.java create mode 100644 langtools/test/tools/javac/diags/examples/AnnoValueMustBeAnnotation.java create mode 100644 langtools/test/tools/javac/diags/examples/AnnoValueMustBeClassLiteral.java create mode 100644 langtools/test/tools/javac/diags/examples/AnnosWithoutProcessors/AnnosWithoutProcessors.java create mode 100644 langtools/test/tools/javac/diags/examples/AnnosWithoutProcessors/processors/AnnoProc.java create mode 100644 langtools/test/tools/javac/diags/examples/AnnotationMissingValue.java create mode 100644 langtools/test/tools/javac/diags/examples/AnnotationMustBeNameValue.java create mode 100644 langtools/test/tools/javac/diags/examples/AnnotationsNotSupported.java create mode 100644 langtools/test/tools/javac/diags/examples/AnonClassImplInterfaceNoArgs.java create mode 100644 langtools/test/tools/javac/diags/examples/AnonClassImplInterfaceNoQualForNew.java create mode 100644 langtools/test/tools/javac/diags/examples/AnonClassImplInterfaceNoTypeArgs.java create mode 100644 langtools/test/tools/javac/diags/examples/AnonymousClass.java create mode 100644 langtools/test/tools/javac/diags/examples/ArrayAndVarargs.java create mode 100644 langtools/test/tools/javac/diags/examples/ArrayDimMissing.java create mode 100644 langtools/test/tools/javac/diags/examples/ArrayRequired.java create mode 100644 langtools/test/tools/javac/diags/examples/AssertAsIdentifier.java create mode 100644 langtools/test/tools/javac/diags/examples/AssertAsIdentifier2.java create mode 100644 langtools/test/tools/javac/diags/examples/AttrMustBeConstant.java create mode 100644 langtools/test/tools/javac/diags/examples/BadSourceFileHeader/BadSourceFileHeader.java create mode 100644 langtools/test/tools/javac/diags/examples/BadSourceFileHeader/sourcepath/p/A.java create mode 100644 langtools/test/tools/javac/diags/examples/BreakOutsideSwitchLoop.java create mode 100644 langtools/test/tools/javac/diags/examples/CallMustBeFirst.java create mode 100644 langtools/test/tools/javac/diags/examples/CannotCreateArrayWithTypeArgs.java create mode 100644 langtools/test/tools/javac/diags/examples/CantApplyDiamond.java create mode 100644 langtools/test/tools/javac/diags/examples/CantAssignToFinal.java create mode 100644 langtools/test/tools/javac/diags/examples/CantDeref.java create mode 100644 langtools/test/tools/javac/diags/examples/CantExtendIntfAnno.java create mode 100644 langtools/test/tools/javac/diags/examples/CantImplement.java create mode 100644 langtools/test/tools/javac/diags/examples/CantInheritDiffArg.java create mode 100644 langtools/test/tools/javac/diags/examples/CantRefBeforeConstr.java create mode 100644 langtools/test/tools/javac/diags/examples/CantResolve.java create mode 100644 langtools/test/tools/javac/diags/examples/CantResolveArgs.java create mode 100644 langtools/test/tools/javac/diags/examples/CantResolveArgsParams.java create mode 100644 langtools/test/tools/javac/diags/examples/CantResolveLocation.java create mode 100644 langtools/test/tools/javac/diags/examples/CantResolveLocationArgs.java create mode 100644 langtools/test/tools/javac/diags/examples/CantResolveLocationArgsParams.java create mode 100644 langtools/test/tools/javac/diags/examples/CantReturnValueForVoid.java create mode 100644 langtools/test/tools/javac/diags/examples/CatchWithoutTry.java create mode 100644 langtools/test/tools/javac/diags/examples/ClashesWith.java create mode 100644 langtools/test/tools/javac/diags/examples/ClassCantWrite.java create mode 100644 langtools/test/tools/javac/diags/examples/ClassPublicInFile.java create mode 100644 langtools/test/tools/javac/diags/examples/ConcreteInheritanceConflict.java create mode 100644 langtools/test/tools/javac/diags/examples/ConstExprRequired.java create mode 100644 langtools/test/tools/javac/diags/examples/ConstantSVUID.java create mode 100644 langtools/test/tools/javac/diags/examples/ContinueOutsideLoop.java create mode 100644 langtools/test/tools/javac/diags/examples/CountError.java create mode 100644 langtools/test/tools/javac/diags/examples/CountErrorPlural.java create mode 100644 langtools/test/tools/javac/diags/examples/CountWarn.java create mode 100644 langtools/test/tools/javac/diags/examples/CountWarnPlural.java create mode 100644 langtools/test/tools/javac/diags/examples/CyclicAnnoElement.java create mode 100644 langtools/test/tools/javac/diags/examples/CyclicInheritance.java create mode 100644 langtools/test/tools/javac/diags/examples/DefaultAllowedInIntfAnnotationMember.java create mode 100644 langtools/test/tools/javac/diags/examples/DeprecatedFilename.java create mode 100644 langtools/test/tools/javac/diags/examples/DeprecatedFilenameAdditional.java create mode 100644 langtools/test/tools/javac/diags/examples/DeprecatedPlural/DeprecatedClass.java create mode 100644 langtools/test/tools/javac/diags/examples/DeprecatedPlural/DeprecatedFilename.java create mode 100644 langtools/test/tools/javac/diags/examples/DeprecatedPlural/DeprecatedPlural.java create mode 100644 langtools/test/tools/javac/diags/examples/DeprecatedPluralAdditional/DeprecatedClass.java create mode 100644 langtools/test/tools/javac/diags/examples/DeprecatedPluralAdditional/DeprecatedFilename.java create mode 100644 langtools/test/tools/javac/diags/examples/DeprecatedPluralAdditional/DeprecatedPlural.java create mode 100644 langtools/test/tools/javac/diags/examples/DeprecatedPluralAdditional/DeprecatedPluralAdditional.java create mode 100644 langtools/test/tools/javac/diags/examples/DiamondInvalidArg.java create mode 100644 langtools/test/tools/javac/diags/examples/DiamondInvalidArgs.java create mode 100644 langtools/test/tools/javac/diags/examples/DiamondNotSupported.java create mode 100644 langtools/test/tools/javac/diags/examples/DirPathElementNotFound.java create mode 100644 langtools/test/tools/javac/diags/examples/DivZero.java create mode 100644 langtools/test/tools/javac/diags/examples/DoesNotOverride.java create mode 100644 langtools/test/tools/javac/diags/examples/DoesntExist.java create mode 100644 langtools/test/tools/javac/diags/examples/DotClassExpected.java create mode 100644 langtools/test/tools/javac/diags/examples/DuplicateAnnotation.java create mode 100644 langtools/test/tools/javac/diags/examples/DuplicateAnnotationMemberValue.java create mode 100644 langtools/test/tools/javac/diags/examples/DuplicateCaseLabel.java create mode 100644 langtools/test/tools/javac/diags/examples/DuplicateClass.java create mode 100644 langtools/test/tools/javac/diags/examples/DuplicateDefaultLabel.java create mode 100644 langtools/test/tools/javac/diags/examples/ElseWithoutIf.java create mode 100644 langtools/test/tools/javac/diags/examples/EmptyBytecodeIdent.java create mode 100644 langtools/test/tools/javac/diags/examples/EmptyCharLiteral.java create mode 100644 langtools/test/tools/javac/diags/examples/EmptyIf.java create mode 100644 langtools/test/tools/javac/diags/examples/EnclClassRequired.java create mode 100644 langtools/test/tools/javac/diags/examples/EnumAnnoValueMustBeEnumConst.java create mode 100644 langtools/test/tools/javac/diags/examples/EnumAsIdentifier.java create mode 100644 langtools/test/tools/javac/diags/examples/EnumAsIdentifier2.java create mode 100644 langtools/test/tools/javac/diags/examples/EnumCantBeInstantiated.java create mode 100644 langtools/test/tools/javac/diags/examples/EnumConstRequired.java create mode 100644 langtools/test/tools/javac/diags/examples/EnumLabelUnqualified.java create mode 100644 langtools/test/tools/javac/diags/examples/EnumNoFinalize.java create mode 100644 langtools/test/tools/javac/diags/examples/EnumNoSubclassing.java create mode 100644 langtools/test/tools/javac/diags/examples/EnumTypesNotExtensible.java create mode 100644 langtools/test/tools/javac/diags/examples/EnumsMustBeStatic.java create mode 100644 langtools/test/tools/javac/diags/examples/EnumsNotSupported.java create mode 100644 langtools/test/tools/javac/diags/examples/ErrProcMessager/ErrProcMessager.java create mode 100644 langtools/test/tools/javac/diags/examples/ErrProcMessager/processors/AnnoProc.java create mode 100644 langtools/test/tools/javac/diags/examples/ErrSyntheticNameConflict.java create mode 100644 langtools/test/tools/javac/diags/examples/Error.java create mode 100644 langtools/test/tools/javac/diags/examples/ErrorReadingFile.java create mode 100644 langtools/test/tools/javac/diags/examples/ExceptAlreadyCaught.java create mode 100644 langtools/test/tools/javac/diags/examples/ExceptNeverThrown.java create mode 100644 langtools/test/tools/javac/diags/examples/Expected2.java create mode 100644 langtools/test/tools/javac/diags/examples/Expected3.java create mode 100644 langtools/test/tools/javac/diags/examples/FinalParamCantBeAssigned.java create mode 100644 langtools/test/tools/javac/diags/examples/FinallyCannotComplete.java create mode 100644 langtools/test/tools/javac/diags/examples/FinallyWithoutTry.java create mode 100644 langtools/test/tools/javac/diags/examples/FloatNumberTooLarge.java create mode 100644 langtools/test/tools/javac/diags/examples/FloatNumberTooSmall.java create mode 100644 langtools/test/tools/javac/diags/examples/ForeachNotApplicable.java create mode 100644 langtools/test/tools/javac/diags/examples/ForeachNotSupported.java create mode 100644 langtools/test/tools/javac/diags/examples/GenericArrayCreation.java create mode 100644 langtools/test/tools/javac/diags/examples/GenericThrowable.java create mode 100644 langtools/test/tools/javac/diags/examples/GenericsNotSupported.java create mode 100644 langtools/test/tools/javac/diags/examples/HasBeenDeprecated.java create mode 100644 langtools/test/tools/javac/diags/examples/IdentifierExpected.java create mode 100644 langtools/test/tools/javac/diags/examples/IllegalBytecodeIdentChar.java create mode 100644 langtools/test/tools/javac/diags/examples/IllegalChar.java create mode 100644 langtools/test/tools/javac/diags/examples/IllegalComboModifiers.java create mode 100644 langtools/test/tools/javac/diags/examples/IllegalEnumStaticRef.java create mode 100644 langtools/test/tools/javac/diags/examples/IllegalEscapeChar.java create mode 100644 langtools/test/tools/javac/diags/examples/IllegalForwardRef.java create mode 100644 langtools/test/tools/javac/diags/examples/IllegalInitializer.java create mode 100644 langtools/test/tools/javac/diags/examples/IllegalLineEndInCharLit.java create mode 100644 langtools/test/tools/javac/diags/examples/IllegalNonAsciiDigit.java create mode 100644 langtools/test/tools/javac/diags/examples/IllegalQualNotIcls.java create mode 100644 langtools/test/tools/javac/diags/examples/IllegalSelfRef.java create mode 100644 langtools/test/tools/javac/diags/examples/IllegalStartOfExpr.java create mode 100644 langtools/test/tools/javac/diags/examples/IllegalUnderscore.java create mode 100644 langtools/test/tools/javac/diags/examples/IllegalUnicodeEscape.java create mode 100644 langtools/test/tools/javac/diags/examples/ImportRequiresCanonical/ImportRequiresCanonical.java create mode 100644 langtools/test/tools/javac/diags/examples/ImportRequiresCanonical/p/Base.java create mode 100644 langtools/test/tools/javac/diags/examples/ImportRequiresCanonical/p/ExtendsBase.java create mode 100644 langtools/test/tools/javac/diags/examples/ImproperSVUID.java create mode 100644 langtools/test/tools/javac/diags/examples/ImproperTypeInnerRawParam.java create mode 100644 langtools/test/tools/javac/diags/examples/ImproperTypeParamMissing.java create mode 100644 langtools/test/tools/javac/diags/examples/IncomparableTypes.java create mode 100644 langtools/test/tools/javac/diags/examples/IncompatibleTypes1.java create mode 100644 langtools/test/tools/javac/diags/examples/InconvertibleTypes.java create mode 100644 langtools/test/tools/javac/diags/examples/InexactVarargsCall.java create mode 100644 langtools/test/tools/javac/diags/examples/InferredDoNotConformToBounds.java create mode 100644 langtools/test/tools/javac/diags/examples/InheritFromFinal.java create mode 100644 langtools/test/tools/javac/diags/examples/InitializerMustComplete.java create mode 100644 langtools/test/tools/javac/diags/examples/InnerClassCantHaveStatic.java create mode 100644 langtools/test/tools/javac/diags/examples/IntNumberTooLarge.java create mode 100644 langtools/test/tools/javac/diags/examples/InterfaceExpected.java create mode 100644 langtools/test/tools/javac/diags/examples/InterfaceNotAllowed.java create mode 100644 langtools/test/tools/javac/diags/examples/IntfAnnotationCantHaveTypeParams.java create mode 100644 langtools/test/tools/javac/diags/examples/IntfAnnotationMemberClash.java create mode 100644 langtools/test/tools/javac/diags/examples/IntfAnnotationsCantHaveParams.java create mode 100644 langtools/test/tools/javac/diags/examples/IntfAnnotationsCantHaveTypeParams.java create mode 100644 langtools/test/tools/javac/diags/examples/IntfMethodCantHaveBody.java create mode 100644 langtools/test/tools/javac/diags/examples/InvalidAnnoMemberType.java create mode 100644 langtools/test/tools/javac/diags/examples/InvalidBinaryNumber.java create mode 100644 langtools/test/tools/javac/diags/examples/InvalidHexNumber.java create mode 100644 langtools/test/tools/javac/diags/examples/InvalidInferredTypes.java create mode 100644 langtools/test/tools/javac/diags/examples/InvalidInstanceof.java create mode 100644 langtools/test/tools/javac/diags/examples/InvalidMethodDecl.java create mode 100644 langtools/test/tools/javac/diags/examples/KindnameClass.java create mode 100644 langtools/test/tools/javac/diags/examples/KindnameConstructor.java create mode 100644 langtools/test/tools/javac/diags/examples/KindnameMethod.java create mode 100644 langtools/test/tools/javac/diags/examples/KindnameVariable.java create mode 100644 langtools/test/tools/javac/diags/examples/LabelInUse.java create mode 100644 langtools/test/tools/javac/diags/examples/LocalEnum.java create mode 100644 langtools/test/tools/javac/diags/examples/LocalVarNeedsFinal.java create mode 100644 langtools/test/tools/javac/diags/examples/LongSVUID.java create mode 100644 langtools/test/tools/javac/diags/examples/MalformedFpLit.java create mode 100644 langtools/test/tools/javac/diags/examples/MalformedSupported/MalformedSupported.java create mode 100644 langtools/test/tools/javac/diags/examples/MalformedSupported/processors/AnnoProc.java create mode 100644 langtools/test/tools/javac/diags/examples/MethodDoesNotOverride.java create mode 100644 langtools/test/tools/javac/diags/examples/MightBeAssignedInLoop.java create mode 100644 langtools/test/tools/javac/diags/examples/MissingDeprecatedAnnotation.java create mode 100644 langtools/test/tools/javac/diags/examples/MissingMethodBody.java create mode 100644 langtools/test/tools/javac/diags/examples/MissingReturnStatement.java create mode 100644 langtools/test/tools/javac/diags/examples/MissingReturnValue.java create mode 100644 langtools/test/tools/javac/diags/examples/MissingSVUID.java create mode 100644 langtools/test/tools/javac/diags/examples/ModifierNotAllowed.java create mode 100644 langtools/test/tools/javac/diags/examples/MulticatchCantBeAssigned.java create mode 100644 langtools/test/tools/javac/diags/examples/MulticatchMustBeFinal.java create mode 100644 langtools/test/tools/javac/diags/examples/MulticatchNotSupported.java create mode 100644 langtools/test/tools/javac/diags/examples/NameClashSameErasure.java create mode 100644 langtools/test/tools/javac/diags/examples/NameClashSameErasureNoOverride.java create mode 100644 langtools/test/tools/javac/diags/examples/NativeMethodCantHaveBody.java create mode 100644 langtools/test/tools/javac/diags/examples/NeitherConditionalSubtype.java create mode 100644 langtools/test/tools/javac/diags/examples/NewNotAllowedInAnno.java create mode 100644 langtools/test/tools/javac/diags/examples/NoArgs.java create mode 100644 langtools/test/tools/javac/diags/examples/NoExplicitAnnoProcRequested.java create mode 100644 langtools/test/tools/javac/diags/examples/NoInterfaceExpected.java create mode 100644 langtools/test/tools/javac/diags/examples/NoInterfaceHere.java create mode 100644 langtools/test/tools/javac/diags/examples/NoJavaLang.java create mode 100644 langtools/test/tools/javac/diags/examples/NoSuperclass.java create mode 100644 langtools/test/tools/javac/diags/examples/NonStaticCantBeRef.java create mode 100644 langtools/test/tools/javac/diags/examples/NotDefAccessClassIntfCantAccess/NotDefAccessClassIntfCantAccess.java create mode 100644 langtools/test/tools/javac/diags/examples/NotDefAccessClassIntfCantAccess/p/C.java create mode 100644 langtools/test/tools/javac/diags/examples/NotDefPublicCantAccess/NotDefPublicCantAccess.java create mode 100644 langtools/test/tools/javac/diags/examples/NotDefPublicCantAccess/p/C.java create mode 100644 langtools/test/tools/javac/diags/examples/NotEnclClass.java create mode 100644 langtools/test/tools/javac/diags/examples/NotLoopLabel.java create mode 100644 langtools/test/tools/javac/diags/examples/NotWithinBounds.java create mode 100644 langtools/test/tools/javac/diags/examples/Note.java create mode 100644 langtools/test/tools/javac/diags/examples/NoteProcMessager/NoteProcMessager.java create mode 100644 langtools/test/tools/javac/diags/examples/NoteProcMessager/processors/AnnoProc.java create mode 100644 langtools/test/tools/javac/diags/examples/OperatorCantBeApplied.java create mode 100644 langtools/test/tools/javac/diags/examples/Orphaned.java create mode 100644 langtools/test/tools/javac/diags/examples/OverrideDoesntThrow.java create mode 100644 langtools/test/tools/javac/diags/examples/OverrideIncompatibleReturn.java create mode 100644 langtools/test/tools/javac/diags/examples/OverrideMeth.java create mode 100644 langtools/test/tools/javac/diags/examples/OverrideStatic.java create mode 100644 langtools/test/tools/javac/diags/examples/OverrideUncheckedReturn.java create mode 100644 langtools/test/tools/javac/diags/examples/OverrideUncheckedThrown.java create mode 100644 langtools/test/tools/javac/diags/examples/OverrideVarargsExtra.java create mode 100644 langtools/test/tools/javac/diags/examples/OverrideVarargsMissing.java create mode 100644 langtools/test/tools/javac/diags/examples/OverrideWeakerAccess.java create mode 100644 langtools/test/tools/javac/diags/examples/PackageAnnos.java create mode 100644 langtools/test/tools/javac/diags/examples/PackageInfoAlreadySeen/p/package-info.java create mode 100644 langtools/test/tools/javac/diags/examples/PackageInfoAlreadySeen/package-info.java create mode 100644 langtools/test/tools/javac/diags/examples/PathElementNotFound.java create mode 100644 langtools/test/tools/javac/diags/examples/PkgClashWithClass/p/q.java create mode 100644 langtools/test/tools/javac/diags/examples/PkgClashWithClass/p/q/C.java create mode 100644 langtools/test/tools/javac/diags/examples/PossibleFallThrough.java create mode 100644 langtools/test/tools/javac/diags/examples/PossibleLossPrecision.java create mode 100644 langtools/test/tools/javac/diags/examples/PrematureEOF.java create mode 100644 langtools/test/tools/javac/diags/examples/PrintProcessorInfo/PrintProcessorInfo.java create mode 100644 langtools/test/tools/javac/diags/examples/PrintProcessorInfo/processors/AnnoProc.java create mode 100644 langtools/test/tools/javac/diags/examples/PrintRounds/PrintRounds.java create mode 100644 langtools/test/tools/javac/diags/examples/PrintRounds/processors/AnnoProc.java create mode 100644 langtools/test/tools/javac/diags/examples/ProcCantFindClass/ProcCantFindClass.java create mode 100644 langtools/test/tools/javac/diags/examples/ProcCantFindClass/processors/AnnoProc.java create mode 100644 langtools/test/tools/javac/diags/examples/ProcFileReopening/ProcFileReopening.java create mode 100644 langtools/test/tools/javac/diags/examples/ProcFileReopening/processors/AnnoProc.java create mode 100644 langtools/test/tools/javac/diags/examples/ProcIllegalFileName/ProcIllegalFileName.java create mode 100644 langtools/test/tools/javac/diags/examples/ProcIllegalFileName/processors/AnnoProc.java create mode 100644 langtools/test/tools/javac/diags/examples/ProcIncompatibleSourceVersion/ProcIncompatibleSourceVersion.java create mode 100644 langtools/test/tools/javac/diags/examples/ProcIncompatibleSourceVersion/processors/AnnoProc.java create mode 100644 langtools/test/tools/javac/diags/examples/ProcOnlyNoProcs.java create mode 100644 langtools/test/tools/javac/diags/examples/ProcPackageDoesNotExist/ProcPackageDoesNotExist.java create mode 100644 langtools/test/tools/javac/diags/examples/ProcPackageDoesNotExist/processors/AnnoProc.java create mode 100644 langtools/test/tools/javac/diags/examples/ProcTypeRecreate/ProcTypeRecreate.java create mode 100644 langtools/test/tools/javac/diags/examples/ProcTypeRecreate/processors/AnnoProc.java create mode 100644 langtools/test/tools/javac/diags/examples/ProcUnclosedTypeFiles/ProcUnclosedTypeFiles.java create mode 100644 langtools/test/tools/javac/diags/examples/ProcUnclosedTypeFiles/processors/AnnoProc.java create mode 100644 langtools/test/tools/javac/diags/examples/ProcUseImplicit/ProcUseImplicit.java create mode 100644 langtools/test/tools/javac/diags/examples/ProcUseImplicit/processors/AnnoProc.java create mode 100644 langtools/test/tools/javac/diags/examples/ProcUseImplicit/sourcepath/p/SomeClass.java create mode 100644 langtools/test/tools/javac/diags/examples/ProcUseProcOrImplicit/ProcUseProcOrImplicit.java create mode 100644 langtools/test/tools/javac/diags/examples/ProcUseProcOrImplicit/processors/AnnoProc.java create mode 100644 langtools/test/tools/javac/diags/examples/ProcUseProcOrImplicit/sourcepath/p/SomeClass.java create mode 100644 langtools/test/tools/javac/diags/examples/ProcessorCantInstantiate/ProcessorCantInstantiate.java create mode 100644 langtools/test/tools/javac/diags/examples/ProcessorCantInstantiate/processors/AnnoProc.java create mode 100644 langtools/test/tools/javac/diags/examples/ProcessorNotFound.java create mode 100644 langtools/test/tools/javac/diags/examples/ProcessorWrongType/ProcessorWrongType.java create mode 100644 langtools/test/tools/javac/diags/examples/ProcessorWrongType/processors/AnnoProc.java create mode 100644 langtools/test/tools/javac/diags/examples/QualifiedNewStaticClass.java create mode 100644 langtools/test/tools/javac/diags/examples/RawClassUse.java create mode 100644 langtools/test/tools/javac/diags/examples/RecursiveConstrInvocation.java create mode 100644 langtools/test/tools/javac/diags/examples/RedundantCast.java create mode 100644 langtools/test/tools/javac/diags/examples/RefAmbiguous.java create mode 100644 langtools/test/tools/javac/diags/examples/RepeatedAnnotationTarget.java create mode 100644 langtools/test/tools/javac/diags/examples/RepeatedInterface.java create mode 100644 langtools/test/tools/javac/diags/examples/RepeatedModifier.java create mode 100644 langtools/test/tools/javac/diags/examples/ReportAccess.java create mode 100644 langtools/test/tools/javac/diags/examples/ResourceClosed.java create mode 100644 langtools/test/tools/javac/diags/examples/ResourceMayNotBeAssigned.java create mode 100644 langtools/test/tools/javac/diags/examples/ResourceNotApplicableToType.java create mode 100644 langtools/test/tools/javac/diags/examples/ResourceNotReferenced.java create mode 100644 langtools/test/tools/javac/diags/examples/ReturnOutsideMethod.java create mode 100644 langtools/test/tools/javac/diags/examples/StaticImportNotSupported.java create mode 100644 langtools/test/tools/javac/diags/examples/StaticImportOnlyClassesAndInterfaces/Other.java create mode 100644 langtools/test/tools/javac/diags/examples/StaticImportOnlyClassesAndInterfaces/StaticImportOnlyClassesAndInterfaces.java create mode 100644 langtools/test/tools/javac/diags/examples/StaticNotQualifiedByType.java create mode 100644 langtools/test/tools/javac/diags/examples/StringConstRequired.java create mode 100644 langtools/test/tools/javac/diags/examples/StringSwitchNotSupported.java create mode 100644 langtools/test/tools/javac/diags/examples/SunApiFilename.java create mode 100644 langtools/test/tools/javac/diags/examples/SunApiFilenameAdditional.java create mode 100644 langtools/test/tools/javac/diags/examples/SunApiPlural/SunApiFilename.java create mode 100644 langtools/test/tools/javac/diags/examples/SunApiPlural/SunApiPlural.java create mode 100644 langtools/test/tools/javac/diags/examples/SunApiPluralAdditional/SunApiFilename.java create mode 100644 langtools/test/tools/javac/diags/examples/SunApiPluralAdditional/SunApiPlural.java create mode 100644 langtools/test/tools/javac/diags/examples/SunApiPluralAdditional/SunApiPluralAdditional.java create mode 100644 langtools/test/tools/javac/diags/examples/SunProprietary.java create mode 100644 langtools/test/tools/javac/diags/examples/SuperNotAllowedInEnum.java create mode 100644 langtools/test/tools/javac/diags/examples/ThrowsNotAllowedInAnno.java create mode 100644 langtools/test/tools/javac/diags/examples/TryResourceNotSupported.java create mode 100644 langtools/test/tools/javac/diags/examples/TryWithoutCatchOrFinally.java create mode 100644 langtools/test/tools/javac/diags/examples/TryWithoutCatchOrFinallyOrResource.java create mode 100644 langtools/test/tools/javac/diags/examples/TypeAnnotationsNotSupported.java create mode 100644 langtools/test/tools/javac/diags/examples/TypeFoundRequired.java create mode 100644 langtools/test/tools/javac/diags/examples/TypeNoParams.java create mode 100644 langtools/test/tools/javac/diags/examples/TypeReqClassArray.java create mode 100644 langtools/test/tools/javac/diags/examples/TypeReqRef.java create mode 100644 langtools/test/tools/javac/diags/examples/TypeVarCantBeDeref.java create mode 100644 langtools/test/tools/javac/diags/examples/TypeVarMayNotBeFollowedByOtherBounds.java create mode 100644 langtools/test/tools/javac/diags/examples/TypesIncompatible.java create mode 100644 langtools/test/tools/javac/diags/examples/UncheckedAssign.java create mode 100644 langtools/test/tools/javac/diags/examples/UncheckedAssignToVar.java create mode 100644 langtools/test/tools/javac/diags/examples/UncheckedCall.java create mode 100644 langtools/test/tools/javac/diags/examples/UncheckedCast.java create mode 100644 langtools/test/tools/javac/diags/examples/UncheckedClash.java create mode 100644 langtools/test/tools/javac/diags/examples/UncheckedFilename.java create mode 100644 langtools/test/tools/javac/diags/examples/UncheckedFilenameAdditional.java create mode 100644 langtools/test/tools/javac/diags/examples/UncheckedGenericArrayCreation.java create mode 100644 langtools/test/tools/javac/diags/examples/UncheckedImplement.java create mode 100644 langtools/test/tools/javac/diags/examples/UncheckedMethodInvocation.java create mode 100644 langtools/test/tools/javac/diags/examples/UncheckedPlural/UncheckedFilename.java create mode 100644 langtools/test/tools/javac/diags/examples/UncheckedPlural/UncheckedPlural.java create mode 100644 langtools/test/tools/javac/diags/examples/UncheckedPluralAdditional/UncheckedFilename1.java create mode 100644 langtools/test/tools/javac/diags/examples/UncheckedPluralAdditional/UncheckedFilename2.java create mode 100644 langtools/test/tools/javac/diags/examples/UncheckedPluralAdditional/UncheckedPluralAdditional.java create mode 100644 langtools/test/tools/javac/diags/examples/UnclosedBytecodeIdent.java create mode 100644 langtools/test/tools/javac/diags/examples/UnclosedCharLiteral.java create mode 100644 langtools/test/tools/javac/diags/examples/UnclosedComment.java create mode 100644 langtools/test/tools/javac/diags/examples/UnclosedStringLiteral.java create mode 100644 langtools/test/tools/javac/diags/examples/UndefinedLabel.java create mode 100644 langtools/test/tools/javac/diags/examples/UndeterminedType1.java create mode 100644 langtools/test/tools/javac/diags/examples/UnmatchedProcessorOptions/UnmatchedProcessorOptions.java create mode 100644 langtools/test/tools/javac/diags/examples/UnmatchedProcessorOptions/processors/AnnoProc.java create mode 100644 langtools/test/tools/javac/diags/examples/UnnamedPackage.java create mode 100644 langtools/test/tools/javac/diags/examples/UnreachableStatement.java create mode 100644 langtools/test/tools/javac/diags/examples/UnreportedException.java create mode 100644 langtools/test/tools/javac/diags/examples/UnreportedExceptionDefaultConstructor.java create mode 100644 langtools/test/tools/javac/diags/examples/UnsupportedBinaryLiteral.java create mode 100644 langtools/test/tools/javac/diags/examples/UnsupportedEncoding.java create mode 100644 langtools/test/tools/javac/diags/examples/UnsupportedFpLit.java create mode 100644 langtools/test/tools/javac/diags/examples/UnsupportedUnderscoreLiteral.java create mode 100644 langtools/test/tools/javac/diags/examples/VarMightAlreadyBeAssigned.java create mode 100644 langtools/test/tools/javac/diags/examples/VarMightNotHaveBeenInitialized.java create mode 100644 langtools/test/tools/javac/diags/examples/VarargsClash.java create mode 100644 langtools/test/tools/javac/diags/examples/VarargsFilename.java create mode 100644 langtools/test/tools/javac/diags/examples/VarargsFilenameAdditional.java create mode 100644 langtools/test/tools/javac/diags/examples/VarargsImplement.java create mode 100644 langtools/test/tools/javac/diags/examples/VarargsNonReifiableType.java create mode 100644 langtools/test/tools/javac/diags/examples/VarargsNotSupported.java create mode 100644 langtools/test/tools/javac/diags/examples/VarargsOverride.java create mode 100644 langtools/test/tools/javac/diags/examples/VarargsPlural/VarargsFilename.java create mode 100644 langtools/test/tools/javac/diags/examples/VarargsPlural/VarargsPlural.java create mode 100644 langtools/test/tools/javac/diags/examples/VarargsPluralAdditional/VarargsFilename.java create mode 100644 langtools/test/tools/javac/diags/examples/VarargsPluralAdditional/VarargsPlural.java create mode 100644 langtools/test/tools/javac/diags/examples/VarargsPluralAdditional/VarargsPluralAdditional.java create mode 100644 langtools/test/tools/javac/diags/examples/Verbose.java create mode 100644 langtools/test/tools/javac/diags/examples/VoidNotAllowed.java create mode 100644 langtools/test/tools/javac/diags/examples/WarnForwardRef.java create mode 100644 langtools/test/tools/javac/diags/examples/WarnProcMessager/WarnProcMessager.java create mode 100644 langtools/test/tools/javac/diags/examples/WarnProcMessager/processors/AnnoProc.java create mode 100644 langtools/test/tools/javac/diags/examples/WarnSelfRef.java create mode 100644 langtools/test/tools/javac/diags/examples/WarnSyntheticNameConflict.java create mode 100644 langtools/test/tools/javac/diags/examples/WarningAndWerror.java create mode 100644 langtools/test/tools/javac/diags/examples/WhereCaptured.java create mode 100644 langtools/test/tools/javac/diags/examples/WhereCaptured1.java create mode 100644 langtools/test/tools/javac/diags/examples/WhereIntersection.java create mode 100644 langtools/test/tools/javac/diags/examples/WhereTypeVar.java create mode 100644 langtools/test/tools/javac/diags/examples/WrongNumberTypeArgs.java diff --git a/langtools/make/build.xml b/langtools/make/build.xml index 1abad67a9df..d269f396534 100644 --- a/langtools/make/build.xml +++ b/langtools/make/build.xml @@ -322,6 +322,35 @@ datafile="${build.coverage.dir}/cobertura.ser"/> + + + + + + + + + + + + + + + +